每天SQL查询出勤时间

问题描述

我是sql Server的新手;我很难编写此查询

这是我的示例数据:

| id |in_2020_11_01 | out_2020_11_01  |  in_2020_11_02 | out_2020_11_02 |
+----+--------------+-----------------+----------------+----------------+
| 1  |  07:30:00    |   15:50:00      |   07:31:00     |    15:46:00    |
| 2  |  07:30:00    |   15:54:00      |   00:00:00     |    00:00:00    |

这是我需要的结果:

DoAssert

如何生成结果?有可能得到这样的结果吗?

预先感谢

解决方法

您需要使用dynamic T-SQL并构建一个PIVOT语句。这是完整的工作示例:

DROP TABLE IF EXISTS #DataSource;

CREATE TABLE #DataSource
(
    [Id] INT,[date] DATE,[time] TIME
);

INSERT INTO #DataSource ([Id],[date],[time])
VALUES (1,'2020-11-1','07:30:00'),(1,'15:50:00'),(2,'15:54:00'),'2020-11-2','07:31:00'),'15:46:00');

DECLARE @ColumnsPIVOT VARCHAR(MAX),@ColumnsSELECT VARCHAR(MAX),@DyanmicTSQLSTatement NVARCHAR(MAX);

WITH DataSource ([date],[prefix],[column_name]) AS
(
    SELECT DISTINCT [date],[prefix] + '_' + REPLACE([date],'-','_')
    FROM #DataSource
    CROSS APPLY
    (
        VALUES ('in'),('out')
    ) DS ([prefix])
)
SELECT @ColumnsPIVOT = STUFF
                        (
                            (
                                SELECT ',' + QUOTENAME([column_name])
                                FROM DataSource
                                ORDER BY [date],[prefix]
                                FOR XML PATH(''),TYPE
                            ).value('.','VARCHAR(MAX)'),1,''
                        ),@ColumnsSELECT = STUFF
                        (
                            (
                                SELECT ',ISNULL(' + QUOTENAME([column_name]) + ',''00:00:00'') AS ' + QUOTENAME([column_name])
                                FROM DataSource
                                ORDER BY [date],''
                        );


    -- SQL Server 2017+
    /*
    WITH DataSource ([date],[column_name]) AS
    (
        SELECT DISTINCT [date],'_')
        FROM #DataSource
        CROSS APPLY
        (
            VALUES ('in'),('out')
        ) DS ([prefix])
    )
    SELECT @ColumnsPIVOT = STRING_AGG(QUOTENAME([column_name]),',') WITHIN GROUP(ORDER BY [date],[prefix]),@ColumnsSELECT = STRING_AGG('ISNULL(' + QUOTENAME([column_name]) + ',''00:00:00'') AS ' + QUOTENAME([column_name]),[prefix])
    FROM DataSource;
    */
    
SET @DyanmicTSQLSTatement= 'SELECT [ID],' + @ColumnsSELECT + '
                            FROM
                            (
                                SELECT [id],CASE ROW_NUMBER() OVER (PARTITION BY [ID],[Date] ORDER BY [Time])
                                            WHEN 1 THEN ''in''
                                            WHEN 2 THEN ''out''
                                       END + ''_'' + REPLACE([date],''-'',''_''),[time]
                                FROM #DataSource
                            ) DS ([id],[time])
                            PIVOT
                            (
                                MAX([time]) FOR [date] IN (' + @ColumnsPIVOT +')
                            ) PVT';

EXEC sp_executesql @DyanmicTSQLSTatement;

enter image description here