左联接使用不同?

时间:2018-12-20 14:47:26

标签: sql-server

最初,我桌上有15名员工。其中两个具有相同的姓氏。

如果我将E.MAT_EMP的选择保持不变,它可以正常工作,并且将选择15名员工。

如果我删除了它(因为我不想显示它),则除了行数,名字,姓氏和月份。它返回给我14行而不是15行。检查后,显然是我具有相同的LastName / FirstName的行之一。

@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)

输出如下:

enter image description here

我的目标是在保留15行的同时简单地删除该列。

3 个答案:

答案 0 :(得分:0)

用要显示的列名替换*,不要将其从子查询中删除。

    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

答案 1 :(得分:0)

SELECT 语句的最终查询中,指定要显示的列名: [N°],[LastName],[FirstName] ,因为*表示您想要显示以前选择的所有列。

答案 2 :(得分:0)

检查以下两个枢轴示例,以了解PIVOT如何按所有非聚合列隐式分组:

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

第二个枢轴:

-- 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

结果:

EmployeeName    A   B       C
Leonard         10  NULL    45
Mark            20  15      5
Mary            40  10      100

旋转时,将旋转的行的值将转换为列名。您可以在SELECT上引用这些列名(可以避免使用*):

SELECT
    P.EmployeeID,
    P.EmployeeName,

    P.A, -- Pivot values as column names
    P.B,
    P.C
FROM
    #EmployeeData AS S
    PIVOT (
        SUM(S.Number) FOR S.Type IN ([A], [B], [C])
    ) AS P

您需要做的是使用E.MAT_EMP(必须在子查询中)进行数据透视,以使您的员工数据不会被分组,然后不要列表放在SELECT上。

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)

如果已打印,则为结果(对于某些示例日期值,我进行了硬编码):

Declare @D1 date = '2018-12-16'
Declare @D2 date = '2018-12-21'

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:
    [1],[2],[3],[4],[5],[6] 

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 ([1],[2],[3],[4],[5],[6]) 
    ) pvt