SQL 具有多行输出的服务器数据透视表

SQL Server Pivot with Multiple Rows Output

我在 Table 中有以下数据。

我需要以下格式的输出。

我试过旋转但似乎无法解决它。 有人可以在这里指导我吗?

提前致谢。

编辑: 文本格式的数据。

EmployeeID ShiftCode AttendanceDate inDateTime outDateTime OverTimeHours
26 ShiftCC1 01-03-2022 01-03-2022 09:10 01-03-2022 18:10 1
26 ShiftCC1 02-03-2022 02-03-2022 09:15 02-03-2022 18:15 2
26 ShiftCC1 03-03-2022 03-03-2022 09:05 03-03-2022 18:05 2
26 ShiftCC1 04-03-2022 04-03-2022 09:10 04-03-2022 18:10 1
26 ShiftCC1 05-03-2022 05-03-2022 09:13 05-03-2022 18:13 2
26 ShiftCC1 06-03-2022 06-03-2022 09:14 06-03-2022 18:14 3
26 ShiftCC1 07-03-2022 07-03-2022 09:16 07-03-2022 18:16 2
26 ShiftCC1 08-03-2022 08-03-2022 09:30 08-03-2022 18:30 1
26 ShiftCC1 09-03-2022 09-03-2022 09:20 09-03-2022 18:20 2
26 ShiftCC1 10-03-2022 10-03-2022 09:25 10-03-2022 18:25 3

以文本格式输出:

EmployeeID ShiftCode DataType 01-03-2022 02-03-2022 03-03-2022 04-03-2022 05-03-2022 06-03-2022 07-03-2022 08-03-2022 09-03-2022 10-03-2022
26 ShiftCC1 InDateTime 01-03-2022 09:10 02-03-2022 09:15 03-03-2022 09:05 04-03-2022 09:10 05-03-2022 09:13 06-03-2022 09:14 07-03-2022 09:16 08-03-2022 09:30 09-03-2022 09:20 10-03-2022 09:25
26 ShiftCC1 OutDateTime 01-03-2022 18:10 02-03-2022 18:15 03-03-2022 18:05 04-03-2022 18:10 05-03-2022 18:13 06-03-2022 18:14 07-03-2022 18:16 08-03-2022 18:30 09-03-2022 18:20 10-03-2022 18:25
26 ShiftCC1 OverTimeHours 1 2 2 1 2 3 2 1 2 3

首先,您的数据集无法得到您想要的准确输出。您需要放弃加班列,因为在旋转这些列后会自动转换为日期类型,或者您可以更改列的数据类型(我为此使用了视图)。

此外,我假设您的“AttendanceDate”是动态的,所以我使用了动态解决方案。

I used @Taryn' s solution here:

选项 1:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.att_date) 
            FROM test1 c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT idx, name, ' + @cols + ' from 
            (
                select idx,
                       name,
                    att_date,
                    att_entry
                from test1
           ) x
            pivot 
            (
                 max(att_entry)
                for att_date in (' + @cols + ')
            ) p 
            union 
            SELECT idx, name, ' + @cols + ' from 
            (
                select idx,
                       name,
                    att_date,
                    att_out
                from test1
           ) x
            pivot 
            (
                 max(att_out)
                for att_date in (' + @cols + ')
            ) p '

execute(@query)

DBFiddle_Option1:

选项2:

您可以创建这样的视图来绕过列不兼容问题。

create view test2
as select idx, name as name, convert(varchar, att_date) as att_date,
convert(varchar, att_entry) as att_entry,
convert(varchar, att_out) as att_out,
convert(varchar, overtime) as overtime
from test1;

那么你可以使用这个:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.att_date) 
            FROM test2 c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT idx, name, ' + @cols + ' from 
            (
                select idx,
                       name,
                    att_date,
                    overtime
                from test2
           ) x
            pivot 
            (
                 max(overtime)
                for att_date in (' + @cols + ')
            ) p 
            union 
            SELECT idx, name, ' + @cols + ' from 
            (
                select idx,
                       name,
                    att_date,
                    att_out
                from test2
           ) x
            pivot 
            (
                 max(att_out)
                for att_date in (' + @cols + ')
            ) p 
            union 
            SELECT idx, name, ' + @cols + ' from 
            (
                select idx,
                       name,
                    att_date,
                    att_entry
                from test2
           ) x
            pivot 
            (
                 max(att_entry)
                for att_date in (' + @cols + ')
            ) p order by 3 desc'

execute(@query)

DBFiddle_Option2:

注意:如果不将数据转换为字符串,最后看起来像这样: