如果每列中每个员工只有一个值,则SQL Server中的多行将转换为单行

如果每列中每个员工只有一个值,则SQL Server中的多行将转换为单行,sql,sql-server,Sql,Sql Server,如何做到这一点,请帮助 我有以下数据。这是本周的数据样本。我希望每个员工姓名/CrewID有一行(除非一个员工在一个日期中有两个值) 如果原始数据如下所示: 2018-08-05 2018-08-06 2018-08-07 2018-08-08 2018-08-09 2018-08-10 2018-08-11 CrewID EmployeeName ------------ ------------ ------------ ------------ -

如何做到这一点,请帮助

我有以下数据。这是本周的数据样本。我希望每个员工姓名/CrewID有一行(除非一个员工在一个日期中有两个值)

如果原始数据如下所示:

2018-08-05   2018-08-06   2018-08-07   2018-08-08   2018-08-09   2018-08-10   2018-08-11   CrewID    EmployeeName   
 ------------ ------------ ------------ ------------ ------------ ------------ ------------ -------- ---------------- 
  NULL         174          173          172          171          NULL         NULL              9   Kanhaiya        
  NULL         NULL         NULL         NULL         NULL         178          NULL              9   Kanhaiya        
  NULL         174          173          172          171          NULL         NULL              8   Santanu Maulik  
  NULL         NULL         NULL         NULL         NULL         178          NULL              8   Santanu Maulik  
  2018-08-05   2018-08-06   2018-08-07   2018-08-08   2018-08-09   2018-08-10   2018-08-11   CrewID   EmployeeName  
 ------------ ------------ ------------ ------------ ------------ ------------ ------------ -------- -------------- 
  NULL         174          173          172           171         NULL         NULL              9   Kanhaiya      
  NULL         NULL         NULL         NULL          163         178          NULL              9   Kanhaiya     
上述原件的输出应为每人一行,如下所示

    2018-08-05   2018-08-06   2018-08-07   2018-08-08   2018-08-09   2018-08-10   2018-08-11   CrewID    EmployeeName   
 ------------ ------------ ------------ ------------ ------------ ------------ ------------ -------- ---------------- 
  NULL         174          173          172          171          178          NULL              9   Kanhaiya  
  NULL         174          173          172          171          178          NULL              8   Santanu Maulik  
但在某些情况下,每个员工的数据可能会被分为多行,比如员工在一个日期有多个值,例如“2018-08-10”

如果原始数据如下所示:

2018-08-05   2018-08-06   2018-08-07   2018-08-08   2018-08-09   2018-08-10   2018-08-11   CrewID    EmployeeName   
 ------------ ------------ ------------ ------------ ------------ ------------ ------------ -------- ---------------- 
  NULL         174          173          172          171          NULL         NULL              9   Kanhaiya        
  NULL         NULL         NULL         NULL         NULL         178          NULL              9   Kanhaiya        
  NULL         174          173          172          171          NULL         NULL              8   Santanu Maulik  
  NULL         NULL         NULL         NULL         NULL         178          NULL              8   Santanu Maulik  
  2018-08-05   2018-08-06   2018-08-07   2018-08-08   2018-08-09   2018-08-10   2018-08-11   CrewID   EmployeeName  
 ------------ ------------ ------------ ------------ ------------ ------------ ------------ -------- -------------- 
  NULL         174          173          172           171         NULL         NULL              9   Kanhaiya      
  NULL         NULL         NULL         NULL          163         178          NULL              9   Kanhaiya     
上述原始数据的输出应如下所示

  2018-08-05   2018-08-06   2018-08-07   2018-08-08   2018-08-09   2018-08-10   2018-08-11   CrewID   EmployeeName  
 ------------ ------------ ------------ ------------ ------------ ------------ ------------ -------- -------------- 
  NULL         174          173          172          171          178           NULL              9   Kanhaiya      
  NULL         NULL         NULL         NULL         163          NULL          NULL              9   Kanhaiya   
我已经设法用存储过程获取了数据

这是存储过程的主要逻辑部分:

ALTER PROCEDURE [dbo].[GetDataForCustomWeekViewReport]
    @Week AS INT, 
    @typeOfData AS VARCHAR(10)
AS
BEGIN
    DECLARE @weekAdjustAdd INT

    SET NOCOUNT ON;

    SET DATEFIRST 7;
    SET @weekAdjustAdd = (@Week - 1) * 7

    DECLARE @SQLQuery AS NVARCHAR(MAX)
    DECLARE @PivotColumns AS NVARCHAR(MAX)

    ----------------------------- 
    -- Get unique values of pivot column  

    SELECT   
        @PivotColumns= COALESCE(@PivotColumns + ',','') + QUOTENAME(WORKDAYS)
    FROM 
        (SELECT DISTINCT WORKDAYS 
         FROM  
             (SELECT 
                  DATEADD(DAY, @weekAdjustAdd, CAST(DATEADD(WEEK, DATEDIFF(DAY, -1, GETDATE()) / 7, -1) AS date)) AS WORKDAYS 
              UNION
              SELECT 
                  DATEADD(DAY, @weekAdjustAdd, CAST(DATEADD(WEEK, DATEDIFF(DAY, -1, GETDATE()) / 7, 0) AS date)) AS WORKDAYS 
              UNION
              SELECT 
                  DATEADD(DAY, @weekAdjustAdd, CAST(DATEADD(WEEK, DATEDIFF(DAY, -1, GETDATE()) / 7, 1) AS date)) AS WORKDAYS 
              UNION
              SELECT 
                  DATEADD(DAY, @weekAdjustAdd, CAST(DATEADD(WEEK,  DATEDIFF(DAY, -1, GETDATE()) / 7, 2) AS date)) AS WORKDAYS 
              UNION
              SELECT 
                  DATEADD(DAY, @weekAdjustAdd, CAST(DATEADD(WEEK, DATEDIFF(DAY, -1, GETDATE()) / 7, 3) AS date)) AS WORKDAYS 
              UNION
              SELECT 
                   DATEADD(DAY, @weekAdjustAdd, CAST(DATEADD(WEEK,  DATEDIFF(DAY, -1, GETDATE()) / 7, 4) AS date)) AS WORKDAYS 
              UNION
              SELECT 
                  DATEADD(DAY, @weekAdjustAdd, CAST(DATEADD(WEEK, DATEDIFF(DAY, -1, GETDATE()) / 7, 5) AS date)) AS WORKDAYS 
            ) i) AS PivotExample

  IF (@typeOfData = 'f')
  BEGIN   
 --Get unique values of pivot column   

--Create the dynamic query with all the values for 
--pivot column at runtime
 --',JOBID, JobInfo,CrewID, EmployeeName,Color
  -- ,JI.INumber + '' - '' + JI.ITitle AS JobInfo, M.Color,
SET   @SQLQuery = 
    N'
    DECLARE @Week AS int
    DECLARE @weekAdjustAdd int
    SET @Week=1
    SET DATEFIRST 7;
    SET @weekAdjustAdd = (@Week - 1) * 7 
    SELECT ' +   @PivotColumns + ', CrewID, EmployeeName
   FROM (


SELECT J.ID AS JOBID, C.ID AS CrewID ,c.CrewName AS EmployeeName ,  JI.ID AS JOBINSTANCE_ID,JI.WORKDAYS 

    FROM  [dbo].[Job] J 
    LEFT JOIN [dbo].[Job_Instances] JI ON J.ID=JI.JOBID
    LEFT JOIN [dbo].[Instance_Employee_Relation] IER ON JI.ID=IER.JobInstanceID 
    LEFT JOIN [dbo].[Crew] C  ON C.Id = IER.EMPLOYEEID 
    INNER JOIN [dbo].[Manager] M  ON M.Id = JI.ManagerID
    INNER JOIN dbo.JobType JT ON JT.ID = JI.JobTypeID
    WHERE   ( C.EmployeeTypeID=1 OR C.EmployeeTypeID IS NULL) AND JI.TYPE = ''F'' AND JI.WORKDAYS BETWEEN DATEADD(DAY,'+CONVERT(VARCHAR(20) ,@weekAdjustAdd)+', CAST(DATEADD(WEEK, DATEDIFF(DAY, -1, GETDATE()) / 7, -1) AS date)) AND DATEADD(DAY,'+ CONVERT(VARCHAR(20) ,@weekAdjustAdd)+', CAST(DATEADD(WEEK, DATEDIFF(DAY, -1, GETDATE()) / 7, 5) AS date)) 
)i 
 PIVOT( SUM(JobInstance_ID) 
    FOR [WORKDAYS] IN (' + @PivotColumns + ')) AS P ORDER BY CASE WHEN EmployeeName IS NULL THEN 1 ELSE 0 END, EmployeeName'


--Execute dynamic query
EXEC sp_executesql @SQLQuery




  END
下面是相关表的主模式部分。

更新

@文试图帮助我,做得很好,但如果我每个员工只有2行,他的答案是有效的,但如果我每个员工有2行以上,他的解决方案是无效的

原始数据

2018-08-05   2018-08-06   2018-08-07   2018-08-08   2018-08-09   2018-08-10   2018-08-11   CrewID    EmployeeName   
 ------------ ------------ ------------ ------------ ------------ ------------ ------------ -------- ---------------- 
  NULL         174          173          172          171          NULL         NULL              9   Kanhaiya        
  NULL         NULL         NULL         NULL         NULL         178          NULL              9   Kanhaiya        
  NULL         NULL         NULL         NULL         183          182          NULL              8   Santanu Maulik  
  NULL         NULL         NULL         NULL         NULL         178          NULL              8   Santanu Maulik  
  NULL         174          173          172          171          NULL         NULL              8   Santanu Maulik
使用@Ven的解决方案输出(不适用于CrewID 8,因为他有3行,但适用于CrewID 9,因为他有2行。)


通过3个不同的步骤来满足需求。没有其他肮脏的方法可以做到这一点:)

1) 通过自联接(左联接)获取表中的上一行和下一行

2) 用于从下一行获取值的大小写表达式,其中第一行的值为null且为非null 第二排

  DECLARE @table TABLE (
    id INT identity(1, 1)
    ,[2018-08-05] INT
    ,[2018-08-06] INT
    ,[2018-08-07] INT
    ,[2018-08-08] INT
    ,[2018-08-09] INT
    ,[2018-08-10] INT
    ,[2018-08-11] INT
    ,CrewID INT
    ,EmployeeName VARCHAR(20)
    )

INSERT @table
------------ ------------ ------------ ------------ ------------ ------------ ------------ -------- ---------------- 
SELECT NULL
    ,174
    ,173
    ,172
    ,171
    ,NULL
    ,NULL
    ,9
    ,'Kanhaiya'

UNION ALL

SELECT NULL
    ,NULL
    ,NULL
    ,NULL
    ,163
    ,178
    ,NULL
    ,9
    ,'Kanhaiya'

UNION ALL

SELECT NULL
    ,174
    ,173
    ,172
    ,171
    ,NULL
    ,NULL
    ,8
    ,'Santanu Maulik'

UNION ALL

SELECT NULL
    ,NULL
    ,NULL
    ,NULL
    ,NULL
    ,178
    ,NULL
    ,8
    ,'Santanu Maulik';
2) 大小写表达式如果两行相等,则第二行中的值为空

  DECLARE @table TABLE (
    id INT identity(1, 1)
    ,[2018-08-05] INT
    ,[2018-08-06] INT
    ,[2018-08-07] INT
    ,[2018-08-08] INT
    ,[2018-08-09] INT
    ,[2018-08-10] INT
    ,[2018-08-11] INT
    ,CrewID INT
    ,EmployeeName VARCHAR(20)
    )

INSERT @table
------------ ------------ ------------ ------------ ------------ ------------ ------------ -------- ---------------- 
SELECT NULL
    ,174
    ,173
    ,172
    ,171
    ,NULL
    ,NULL
    ,9
    ,'Kanhaiya'

UNION ALL

SELECT NULL
    ,NULL
    ,NULL
    ,NULL
    ,163
    ,178
    ,NULL
    ,9
    ,'Kanhaiya'

UNION ALL

SELECT NULL
    ,174
    ,173
    ,172
    ,171
    ,NULL
    ,NULL
    ,8
    ,'Santanu Maulik'

UNION ALL

SELECT NULL
    ,NULL
    ,NULL
    ,NULL
    ,NULL
    ,178
    ,NULL
    ,8
    ,'Santanu Maulik';
脚本:

 WITH CTE
    AS (
        SELECT rownum = ROW_NUMBER() OVER (
                PARTITION BY p.crewid ORDER BY p.crewID
                )
            ,p.*
        FROM @table p
        )
        ,ct2
    AS (
        SELECT TOP 100 PERCENT cte.CrewID
            ,cte.employeename
            ,CASE WHEN cte.[2018-08-05] IS NULL THEN nex.[2018-08-05] ELSE cte.[2018-08-05] END [2018-08-05]
            ,CASE WHEN cte.[2018-08-06] IS NULL THEN nex.[2018-08-06] ELSE cte.[2018-08-06] END [2018-08-06]
            ,CASE WHEN cte.[2018-08-07] IS NULL THEN nex.[2018-08-07] ELSE cte.[2018-08-07] END [2018-08-07]
            ,CASE WHEN cte.[2018-08-08] IS NULL THEN nex.[2018-08-08] ELSE cte.[2018-08-08] END [2018-08-08]
            ,CASE WHEN cte.[2018-08-09] IS NULL THEN nex.[2018-08-09] ELSE cte.[2018-08-09] END [2018-08-09]
            ,CASE WHEN cte.[2018-08-10] IS NULL THEN nex.[2018-08-10] ELSE cte.[2018-08-10] END [2018-08-10]
            ,CASE WHEN cte.[2018-08-11] IS NULL THEN nex.[2018-08-11] ELSE cte.[2018-08-11] END [2018-08-11]
        FROM CTE
        LEFT JOIN CTE prev ON prev.rownum = CTE.rownum - 1
        LEFT JOIN CTE nex ON nex.rownum = CTE.rownum + 1
        ORDER BY cte.CrewID
        )
        ,ct3
    AS (
        SELECT DISTINCT CrewID
            ,EmployeeName
            ,CASE WHEN [2018-08-05] = LEAD([2018-08-05]) OVER (
                        PARTITION BY crewid ORDER BY [2018-08-05]
                        ) THEN NULL ELSE [2018-08-05] END [2018-08-05]
            ,CASE WHEN [2018-08-06] = LEAD([2018-08-06]) OVER (
                        PARTITION BY crewid ORDER BY [2018-08-06]
                        ) THEN NULL ELSE [2018-08-06] END [2018-08-06]
            ,CASE WHEN [2018-08-07] = LEAD([2018-08-07]) OVER (
                        PARTITION BY crewid ORDER BY [2018-08-07]
                        ) THEN NULL ELSE [2018-08-07] END [2018-08-07]
            ,CASE WHEN [2018-08-08] = LEAD([2018-08-08]) OVER (
                        PARTITION BY crewid ORDER BY [2018-08-08]
                        ) THEN NULL ELSE [2018-08-08] END [2018-08-08]
            ,CASE WHEN [2018-08-09] = LEAD([2018-08-09]) OVER (
                        PARTITION BY crewid ORDER BY [2018-08-09]
                        ) THEN NULL ELSE [2018-08-09] END [2018-08-09]
            ,CASE WHEN [2018-08-10] = LEAD([2018-08-10]) OVER (
                        PARTITION BY crewid ORDER BY [2018-08-10]
                        ) THEN NULL ELSE [2018-08-10] END [2018-08-10]
            ,CASE WHEN [2018-08-11] = LEAD([2018-08-11]) OVER (
                        PARTITION BY crewid ORDER BY [2018-08-11]
                        ) THEN NULL ELSE [2018-08-11] END [2018-08-11]
        FROM ct2
        )
    SELECT *
    FROM ct3
    WHERE isnull([2018-08-05], 0) + isnull([2018-08-06], 0) + isnull([2018-08-07], 0) + isnull([2018-08-08], 0) + isnull([2018-08-09], 0) + isnull([2018-08-10], 0) + isnull([2018-08-11], 0) > 0

你们的问题还不清楚,我猜最后一张表是你们的预期输出?。您是否有任何努力,请让我们知道。@Ven yes最后一个表是第三个表的预期输出。对于第一个表,预期输出为第二个表。表示两个条件都应支持。第一个表是原始数据吗?你们在栏里有日期吗?请您发布您的模式,样本数据请提供一些您现有的queries@squirral第一个表和第三个表可以是原始数据的两个示例。。。这是我通过数据透视从大型动态查询中获得的数据。如果我从这里得到任何帮助,我可以将其存储在临时表中,并根据需要归档进一步的需求。好的,让我试试&如果有超过2行,它会起作用吗?我的实际数据中可能有n行。我的示例只有两行。我正在尝试在存储过程中实现您的答案。这将需要时间,因为我的列都是动态列。我必须将当前查询到的数据存储到临时表中,然后再应用您的答案。一旦完成,我会让你知道的。谢谢。它只适用于两排。如果我每个员工有超过2行,则它不起作用。