Sql server 使用distinct左连接?
最初,我的桌子上有15名员工。其中两个姓相同 如果我让Sql server 使用distinct左连接?,sql-server,Sql Server,最初,我的桌子上有15名员工。其中两个姓相同 如果我让E.MAT_EMP选项保持原样,它工作正常,将有15名员工被选中 如果我删除它(因为我不想显示它),除了行数、Firstname、Lastname和月天数。它返回给我的是14行而不是15行。检查后,它显然是我有相同姓氏/名的行之一 @StartDate date, @EndDate date as begin Declare @D1 date = @StartDate Declare @D2 date = @EndDate Declar
E.MAT_EMP
选项保持原样,它工作正常,将有15名员工被选中
如果我删除它(因为我不想显示它),除了行数、Firstname、Lastname和月天数。它返回给我的是14行而不是15行。检查后,它显然是我有相同姓氏/名的行之一
@StartDate date,
@EndDate date
as
begin
Declare @D1 date = @StartDate
Declare @D2 date = @EndDate
Declare @Cols varchar(max) = (Select Stuff((Select ',[' +cast(N as varchar(25))+']' From (Select Top (DateDiff(DAY,@D1,@D2)+1) N=Row_Number() Over (Order By (Select Null)) From master..spt_values n1) A For XML Path ('')),1,1,'') )
Declare @SQL varchar(max) = '
Declare @D1 date = '''+cast(@D1 as varchar(50))+'''
Declare @D2 date = '''+cast(@D2 as varchar(50))+'''
Select ROW_NUMBER() OVER (ORDER BY LastName ASC) as [N°],*
From (
Select E.MAT_EMP, NOM_EMP as [LastName],PRENOM_EMP as [FirstName],
Item = day(d)
,Value =
case when (D between DEBUT_DRC and FIN_DRC) and STATUS_DRC = ''Accepté'' then ''RC''
when (D between DEBUT_DAB and FIN_DAB) and STATUS_DAB = ''Accepté'' then ''ABS''
when (D between DC_DEBUT and DC_FIN) and STATUS_DC = ''Accepté'' then DCon.CODE_TYPE_CONGE
else ''''
end
From
DEMANDE_RECUPERATION DC RIGHT JOIN EMPLOYE E
ON DC.MAT_EMP = E.MAT_EMP
LEFT JOIN DEMANDE_ABSENCE ABS
ON E.MAT_EMP = ABS.MAT_EMP
LEFT JOIN DEMANDE_CONGE DCon
ON E.MAT_EMP = DCon.MAT_EMP
Cross Join (
Select Top (DateDiff(DAY,@D1,@D2)+1) D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),@D1) From master..spt_values n1
) B
) src
Pivot (max(value) for Item in ('+@Cols+') ) pvt
'
Exec(@SQL)
结果如下:
我的目标是简单地删除该列,同时保留15行。将*替换为要显示的列名,而不要将其从子查询中删除
Select ROW_NUMBER() OVER (ORDER BY LastName ASC) as [N°], [LastName], [FirstName] /*other needed columns here*/
From (
Select E.MAT_EMP, NOM_EMP as [LastName],PRENOM_EMP as [FirstName],
Item = day(d)
,Value =
case when (D between DEBUT_DRC and FIN_DRC) and STATUS_DRC = ''Accepté'' then ''RC''
when (D between DEBUT_DAB and FIN_DAB) and STATUS_DAB = ''Accepté'' then ''ABS''
when (D between DC_DEBUT and DC_FIN) and STATUS_DC = ''Accepté'' then DCon.CODE_TYPE_CONGE
else ''''
end
From
DEMANDE_RECUPERATION DC RIGHT JOIN EMPLOYE E
ON DC.MAT_EMP = E.MAT_EMP
LEFT JOIN DEMANDE_ABSENCE ABS
ON E.MAT_EMP = ABS.MAT_EMP
LEFT JOIN DEMANDE_CONGE DCon
ON E.MAT_EMP = DCon.MAT_EMP
Cross Join (
Select Top (DateDiff(DAY,@D1,@D2)+1) D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),@D1) From master..spt_values n1
) B
) src
Pivot (max(value) for Item in ('+@Cols+') ) pvt
在SELECT语句的最终查询中,指定要显示的列的名称:[N°]、[LastName]、[FirstName],因为*表示要显示以前选择的所有列。检查这两个透视示例,了解如何按所有非聚合列隐式分组:
IF OBJECT_ID('tempdb..#EmployeeData') IS NOT NULL
DROP TABLE #EmployeeData
CREATE TABLE #EmployeeData (
EmployeeID INT,
EmployeeName VARCHAR(100),
Type CHAR(1),
Number INT)
INSERT INTO #EmployeeData (
EmployeeID,
EmployeeName,
Type,
Number)
VALUES
(1, 'Mark', 'A', 10),
(1, 'Mark', 'A', 10),
(1, 'Mark', 'B', 15),
(1, 'Mark', 'C', 5),
(2, 'Leonard', 'A', 10),
(2, 'Leonard', 'C', 45),
(3, 'Mary', 'B', 10),
(3, 'Mary', 'C', 15),
(3, 'Mary', 'C', 25),
(3, 'Mary', 'C', 5),
(4, 'Mary', 'A', 25), -- Diferent ID!
(4, 'Mary', 'A', 15),
(4, 'Mary', 'C', 20),
(4, 'Mary', 'C', 35)
第一支点:
-- Pivot Groups by EmployeeID + EmployeeName (all non-aggregate columns)
SELECT
P.*
FROM
#EmployeeData AS S
PIVOT (
SUM(S.Number) FOR S.Type IN ([A], [B], [C])
) AS P
结果:
EmployeeID EmployeeName A B C
2 Leonard 10 NULL 45
1 Mark 20 15 5
3 Mary NULL 10 45
4 Mary 40 NULL 55
EmployeeName A B C
Leonard 10 NULL 45
Mark 20 15 5
Mary 40 10 100
第二支点:
-- Pivot Groups by EmployeeName (only)
;WITH NoEmployeeName AS
(
SELECT
E.EmployeeName,
E.Type,
E.Number
FROM
#EmployeeData AS E
)
SELECT
P.*
FROM
NoEmployeeName AS S
PIVOT (
SUM(S.Number) FOR S.Type IN ([A], [B], [C])
) AS P
结果:
EmployeeID EmployeeName A B C
2 Leonard 10 NULL 45
1 Mark 20 15 5
3 Mary NULL 10 45
4 Mary 40 NULL 55
EmployeeName A B C
Leonard 10 NULL 45
Mark 20 15 5
Mary 40 10 100
旋转时,正在旋转的行的值将转换为列名。您可以在选择中引用这些列名(您可以避免使用*
):
您需要做的是使用E.MAT_EMP
(必须在子查询中)进行透视,这样您的员工数据就不会按分组,然后不要在选择中列出它
Declare @D1 date = CONVERT(DATE, GETDATE() - 5)
Declare @D2 date = CONVERT(DATE, GETDATE())
Declare @Cols varchar(max) = (Select Stuff((Select ',[' +cast(N as varchar(25))+']' From (Select Top (DateDiff(DAY,@D1,@D2)+1) N=Row_Number() Over (Order By (Select Null)) From master..spt_values n1) A For XML Path ('')),1,1,'') )
Declare @SQL varchar(max) = '
Declare @D1 date = '''+cast(@D1 as varchar(50))+'''
Declare @D2 date = '''+cast(@D2 as varchar(50))+'''
Select
ROW_NUMBER() OVER (ORDER BY LastName ASC) as [N°],
pvt.LastName, -- Grouping columns of pivot operator (without MAT_EMP)
pvt.FirstName,
-- New columns result of pivot:
' + @Cols + '
From (
Select
E.MAT_EMP,
NOM_EMP as [LastName],
PRENOM_EMP as [FirstName],
Item = day(d),
Value = case
when (D between DEBUT_DRC and FIN_DRC) and STATUS_DRC = ''Accepté'' then ''RC''
when (D between DEBUT_DAB and FIN_DAB) and STATUS_DAB = ''Accepté'' then ''ABS''
when (D between DC_DEBUT and DC_FIN) and STATUS_DC = ''Accepté'' then DCon.CODE_TYPE_CONGE
else '''' end
From
DEMANDE_RECUPERATION DC
RIGHT JOIN EMPLOYE E ON DC.MAT_EMP = E.MAT_EMP
LEFT JOIN DEMANDE_ABSENCE ABS ON E.MAT_EMP = ABS.MAT_EMP
LEFT JOIN DEMANDE_CONGE DCon ON E.MAT_EMP = DCon.MAT_EMP
Cross Join (
Select Top (DateDiff(DAY,@D1,@D2)+1)
D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),@D1)
From
master..spt_values n1) B
) src
Pivot (
max(value) for Item in ('+@Cols+')
) pvt
'
PRINT(@SQL)
-- EXEC (@SQL)
如果打印,这是结果(对于我硬编码的一些示例日期值):
我没有仔细检查,但我相信您的pivot函数是通过所有非聚合列隐式分组的(它总是这样做),并且由于聚合,您正在“丢失”一行。如果您从“src”子查询中删除E.MAT_EMP,那么pivot将仅通过NOM_EMP&PRENOM_EMP分组。因此,如果同一姓氏和名字的MAT_EMP超过1,那么可以预期得到的行数会更少。无论如何,如果外部查询中的[N°]、*
被[N°]、[LastName]、[FirstName]、“++@Cols+”
@EzLo在这种情况下的解决方案是什么?@LukStorms我认为应该是“++@Cols+”,因为它是XML。但这不起作用,我得到了列,但对于表示日期的列,我只得到了一个内有+@Cols+的列。这是起作用的,但我应该如何显示这些天的列?在子查询中命名列,然后在主选择中使用这些名称。谢谢,但正如上面和下面所说的,如何显示其他列?哪些列?您刚才说“我的目标是简单地删除该列,同时保留15行”,如果您引用[Item]和[Value],请尝试将它们放在外部查询中的其他行之后,如[N°]、[LastName]、[FirstName]、pvt.[Item]、pvt.[Value]您可以尝试让“第二个”查询的Select语句按原样执行,并在指定最终列名称的位置进行第三个外部查询。