将列名转换为时间

时间:2013-07-31 20:40:35

标签: sql sql-server datetime varchar unpivot

有一个表TABLE,用于存储给定日期内各种时间间隔的值。这一天可以分为每个时间间隔24小时或每个时间间隔为15分钟的96个间隔。 TABLE包含以下列

DATE
INTERVALCOUNT
INT001
INT002
.
.
INT096

我需要以下列格式显示表格中的值,其中基于INTERVALCOUNT值计算时间并显示其关联值

示例输出

DATE        TIME             INTERVALCOUNT  VALUE
2013-04-11  00:00:00.0000000        96      23.43
2013-04-11  00:15:00.0000000        96      26.91
2013-04-11  00:30:00.0000000        96      28.1999999999
2013-04-11  00:45:00.0000000        96      28.77
2013-04-23  00:00:00.0000000        24      18.3099999999
2013-04-23  01:00:00.0000000        24      20.94

CODE

SELECT   [DATE],
        (CASE 
        WHEN [INTERVALCOUNT]=96 THEN CAST(DATEADD(MINUTE,CAST(SUBSTRING([INTERVAL],4,3) AS INT)*15, [DATE]) AS Time)
        WHEN [INTERVALCOUNT]=24 THEN CAST(DATEADD(HOUR,CAST(SUBSTRING([INTERVAL],4,3) AS INT), [DATE]) AS Time)
        END) AS [TIME],
        [INTERVALCOUNT], --24/96 
        [VALUE] 
        FROM ( SELECT [DATE],
            [INTERVALCOUNT], --24/96 
            [INT001], [INT002], [INT003], [INT004], [INT005], [INT006], [INT007], [INT008], 
            [INT009], [INT010], [INT011], [INT012], [INT013], [INT014], [INT015], [INT016],
            [INT017], [INT018], [INT019], [INT020], [INT021], [INT022], [INT023], [INT024],
            [INT025], [INT026], [INT027], [INT028], [INT029], [INT030], [INT031], [INT032],
            [INT033], [INT034], [INT035], [INT036], [INT037], [INT038], [INT039], [INT040], 
            [INT041], [INT042], [INT043], [INT044], [INT045], [INT046], [INT047], [INT048],
            [INT049], [INT050], [INT051], [INT052], [INT053], [INT054], [INT055], [INT056],
            [INT057], [INT058], [INT059], [INT060], [INT061], [INT062], [INT063], [INT064],
            [INT065], [INT066], [INT067], [INT068], [INT069], [INT070], [INT071], [INT072], 
            [INT073], [INT074], [INT075], [INT076], [INT077], [INT078], [INT079], [INT080],
            [INT081], [INT082], [INT083], [INT084], [INT085], [INT086], [INT087], [INT088], 
            [INT089], [INT090], [INT091], [INT092], [INT093], [INT094], [INT095], [INT096] 
            FROM          [TABLE] ) [Source]
        UNPIVOT ([VALUE] FOR [INTERVAL] IN
        ([INT001], [INT002], [INT003], [INT004], [INT005], [INT006], [INT007], [INT008], 
        [INT009], [INT010], [INT011], [INT012], [INT013], [INT014], [INT015], [INT016],
        [INT017], [INT018], [INT019], [INT020], [INT021], [INT022], [INT023], [INT024],
        [INT025], [INT026], [INT027], [INT028], [INT029], [INT030], [INT031], [INT032],
        [INT033], [INT034], [INT035], [INT036], [INT037], [INT038], [INT039], [INT040], 
        [INT041], [INT042], [INT043], [INT044], [INT045], [INT046], [INT047], [INT048],
        [INT049], [INT050], [INT051], [INT052], [INT053], [INT054], [INT055], [INT056],
        [INT057], [INT058], [INT059], [INT060], [INT061], [INT062], [INT063], [INT064],
        [INT065], [INT066], [INT067], [INT068], [INT069], [INT070], [INT071], [INT072], 
        [INT073], [INT074], [INT075], [INT076], [INT077], [INT078], [INT079], [INT080],
        [INT081], [INT082], [INT083], [INT084], [INT085], [INT086], [INT087], [INT088], 
        [INT089], [INT090], [INT091], [INT092], [INT093], [INT094], [INT095], [INT096]) ) [Unpivot]

我已使用UNPIVOT实现了该功能,并且显示时间时使用CAST以及SUBSTRING。有没有更好的方法呢?特别是我将时间间隔转换为时间的部分。

编辑无法更改表格设计

3 个答案:

答案 0 :(得分:1)

  

有更好的方法吗?

取决于更好的含义。例如,TIME计算的以下表达式在代码量方面“更好”:

DATEADD(
  MINUTE,
  CAST(SUBSTRING([INTERVAL],4,3) AS INT) * 1440 / INTERVALCOUNT,
  CAST('00:00' AS time)
) AS [TIME]

您可能还发现它更具可扩展性(事实上,实际上可扩展):如果您需要添加半小时间隔的支持,您只需要开始使用{{1与您的数据。

同时,使用上述代码可以以不太清楚的方式传达意图。因此,如果INTERVALCOUNT = 4824是您96所需的唯一可能值,那么您可能不需要比您已经获得的那部分更多的灵活性代码。

答案 1 :(得分:0)

您还没有提到输出的目的是什么,但我认为它是某种报告?

我认为没有更好的方法可以做到这一点。你有什么UNPIVOT的经典用例,你的解决方案似乎适合我,因为你不能改变底层的数据结构。

答案 2 :(得分:0)

试试这个 -

DECLARE 
      @cols NVARCHAR(MAX)
    , @SQL NVARCHAR(MAX)

SELECT @cols = STUFF((
    SELECT ', [' + c.name + ']'
    FROM sys.columns c
    WHERE c.name LIKE 'INT%'
        AND c.[object_id] = OBJECT_ID('dbo.TABLE')
    FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, '')

SELECT @SQL = '

SELECT 
      [DATE]
    , [TIME] = CASE 
        WHEN [INTERVALCOUNT] = 96 
            THEN CAST(DATEADD(MINUTE, CAST(SUBSTRING([INTERVAL],4,3) AS INT)*15, [DATE]) AS Time)
        WHEN [INTERVALCOUNT] = 24 
            THEN CAST(DATEADD(HOUR, CAST(SUBSTRING([INTERVAL],4,3) AS INT), [DATE]) AS Time)
      END
    , [INTERVALCOUNT]
    , [VALUE] 
FROM ( 
    SELECT [DATE], [INTERVALCOUNT], ' + @cols + ' 
    FROM [TABLE] 
) s
UNPIVOT ([VALUE] FOR [INTERVAL] IN (' + @cols + ') ) up
'

PRINT @SQL
EXEC sys.sp_executesql @SQL