如果每列中每个员工只有一个值,则SQL Server中的多行将转换为单行
如何做到这一点,请帮助 我有以下数据。这是本周的数据样本。我希望每个员工姓名/CrewID有一行(除非一个员工在一个日期中有两个值) 如果原始数据如下所示:如果每列中每个员工只有一个值,则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 ------------ ------------ ------------ ------------ -
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行,则它不起作用。