2

我使用 MS SQL Server 2008
表名是tblDateTimeLog

ID INT(AI)
RecordID INT
DateLog DATE  
TimeLog TIME
DetachmentCode INT
EntryDate DATETIME
IsDeleted BIT
UserID VARCHAR(50)  

我有一个包含这个的表:

RecordID | DateLog    | TimeLog
11       | 2013-06-01 | 07:59:00
11       | 2013-06-01 | 19:01:00
11       | 2013-06-02 | 07:57:00
11       | 2013-06-02 | 19:03:00
11       | 2013-06-03 | 07:49:00
11       | 2013-06-03 | 19:11:00
14       | 2013-06-04 | 08:01:00
14       | 2013-06-04 | 19:03:00
14       | 2013-06-05 | 07:52:00
14       | 2013-06-05 | 19:02:00

一个 Record ID 可以在同一个 DateLog 上有多个 TimeLog

现在我希望它显示如下:
作为列的日期和 MIN(TimeLog) 和 MAX(TimeLog) 之间的总小时数

RecordID | 2013-06-01 | 2013-06-02 | 2013-06-03 | 2013-06-04 | 2013-06-05
11       | 11:02:00   | 11:06:00   | 11:22:00   | NULL       | NULL  
14       | NULL       | NULL       | NULL       | 11:02:00   | 11:10:00  

根据 Mikael 的回答,这可行,但据我了解他的查询,这将返回 MIN(TimeLog):

DECLARE @SQL NVARCHAR(MAX)
DECLARE @ColumnList NVARCHAR(MAX)

SELECT @ColumnList = 
STUFF
    (
        (
            SELECT DISTINCT ','+QUOTENAME(DateLog)
            FROM TESTPIS.dbo.tblDateTimeLog
            WHERE IsDeleted=0 AND DateLog >= '2013-06-15' AND DateLog <= '2013-06-30'
            ORDER BY 1
            FOR XML PATH('')
        ), 1, 1, ''
    )

SET @SQL = 'SELECT P.RecordID, '+@ColumnList+'
                FROM
                    (
                        SELECT RecordID, TimeLog, DateLog FROM TESTPIS.dbo.tblDateTimeLog WHERE isDeleted=0
                    ) AS T
                PIVOT
                    (
                        MIN(TimeLog) FOR DateLog IN ('+@ColumnList+')
                    ) as P'
EXEC (@SQL)

我想返回的就像DATEDIFF(MINUTES,MIN(TimeLog),MAX(TimeLog)

我尝试用这个替换MIN(TimeLog)查询中的
SUM(DATEDIFF(MINUTES,MIN(TimeLog),MAX(TimeLog))

但是,我收到了这个错误
Incorrect syntax near '('.

4

2 回答 2

2

试试这个——

询问:

IF OBJECT_ID (N'tempdb.dbo.#temp') IS NOT NULL
   DROP TABLE #temp

CREATE TABLE #temp
(
        RecordID INT
      , DateLog DATETIME
      , TimeLog TIME
)

INSERT INTO #temp (RecordID, DateLog, TimeLog)
VALUES 
    (11, '2013-06-01', '08:00:00'), (11, '2013-06-02', '09:00:00'),
    (11, '2013-06-03', '10:00:00'), (11, '2013-06-04', '11:00:00'),
    (11, '2013-06-05', '12:00:00'), (14, '2013-06-01', '13:00:00'),
    (14, '2013-06-02', '14:00:00'), (14, '2013-06-03', '15:00:00'),
    (14, '2013-06-04', '16:00:00')

DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = 'SELECT *
FROM (
    SELECT DateLog, RecordID, tt = CAST(TimeLog AS VARCHAR(8)) 
    FROM #temp
) src
PIVOT (
    MAX(tt) 
    FOR DateLog IN (' + STUFF((
    SELECT ', [' + CONVERT(VARCHAR(10), DateLog, 120) + ']'
    FROM #temp
    GROUP BY DateLog
    ORDER BY DateLog
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + ')
) p'

PRINT @SQL

EXEC sys.sp_executesql @SQL

输出:

SELECT *
FROM (
    SELECT DateLog, RecordID, tt = CAST(TimeLog AS VARCHAR(8)) 
    FROM #temp
) src
PIVOT (
    MAX(tt) 
    FOR DateLog IN ([2013-06-01], [2013-06-02], [2013-06-03], [2013-06-04], [2013-06-05])
) p

结果:

RecordID    2013-06-01 2013-06-02 2013-06-03 2013-06-04 2013-06-05
----------- ---------- ---------- ---------- ---------- ----------
11          08:00:00   09:00:00   10:00:00   11:00:00   12:00:00
14          13:00:00   14:00:00   15:00:00   16:00:00   NULL

更新结果:

教授

于 2013-06-14T06:23:29.740 回答
2
select P.RecordID,
       P.[2013-06-01],
       P.[2013-06-02],
       P.[2013-06-03],
       P.[2013-06-04],
       P.[2013-06-05]
from (
     select RecordID,
            TimeLog,
            DateLog
     from YourTable
     ) as T
pivot(min(TimeLog) for DateLog in ([2013-06-01],
                                   [2013-06-02],
                                   [2013-06-03],
                                   [2013-06-04],
                                   [2013-06-05])) as P

要动态构建查询,您必须首先确定列列表应包含的内容。

select distinct DateLog
from YourTable
order by 1

该查询的结果必须转换为逗号分隔的列表,因为这样的数字是无效的列名,您可以使用quotename()将值括在 [] 中。

要构建逗号分隔的列列表,您可以使用for xml path('').

select stuff((select distinct ','+quotename(DateLog)
              from YourTable
              order by 1
              for xml path('')), 1, 1, '')

stuff()是否可以删除第一个逗号。

然后,您只需将它们放在一起并执行您构建的查询。

declare @SQL nvarchar(max)
declare @ColumnList nvarchar(max)

select @ColumnList = stuff((select distinct ','+quotename(DateLog)
                            from YourTable
                            order by 1
                            for xml path('')), 1, 1, '')

set @SQL = '
select P.RecordID, '+@ColumnList+'
from (
     select RecordID,
            TimeLog,
            DateLog
     from YourTable
     ) as T
pivot(min(TimeLog) for DateLog in ('+@ColumnList+')) as P'

exec (@SQL)

SQL小提琴

更新

要获取每天的最大和最小时间日志值之间的差异,您可以在派生表中进行分组,RecordIDDateLog以秒为单位计算最小值和最大值之间的差异,并使用该值使用 dateadd 计算新的时间值。

select P.RecordID,
       P.[2013-06-01],
       P.[2013-06-02],
       P.[2013-06-03],
       P.[2013-06-04],
       P.[2013-06-05]
from (
     select RecordID,
            dateadd(second, datediff(second, min(TimeLog), max(TimeLog)), convert(time(0), '00:00')) as TimeDiff,
            DateLog
     from YourTable
     group by RecordID,
              DateLog
     ) as T
pivot(min(TimeDiff) for DateLog in ([2013-06-01],
                                    [2013-06-02],
                                    [2013-06-03],
                                    [2013-06-04],
                                    [2013-06-05])) as P

动态版:

declare @SQL nvarchar(max)
declare @ColumnList nvarchar(max)

select @ColumnList = stuff((select distinct ','+quotename(DateLog)
                            from YourTable
                            order by 1
                            for xml path('')), 1, 1, '')

set @SQL = '
select P.RecordID, '+@ColumnList+'
from (
     select RecordID,
            dateadd(second, datediff(second, min(TimeLog), max(TimeLog)), convert(time(0), ''00:00'')) as TimeDiff,
            DateLog
     from YourTable
     group by RecordID,
              DateLog
     ) as T
pivot(min(TimeDiff) for DateLog in ('+@ColumnList+')) as P'

exec (@SQL)

SQL小提琴

于 2013-06-14T06:19:33.543 回答