【问题标题】:First value of tomorrow to appear on last cell of today's row明天的第一个值出现在今天行的最后一个单元格上
【发布时间】:2018-09-22 15:56:45
【问题描述】:

感谢大家对 Stack 的支持,我即将解决我的问题。但我对 SQL 中枢轴的日期和时间有疑问。

我有以下疑问:

DECLARE @_SerialNumber NVARCHAR(MAX)        
DECLARE @_DateFrom DATETIME
DECLARE @_DateTo DATETIME


SET @_SerialNumber = '2209'
SET @_DateFrom = '2018-09-20 00:00'
SET @_DateTo = DATEADD(DD, 1, @_DateFrom)

SELECT [Serial], 
       [Channel],
       [ReadingDate],
       [00:15],[00:30],[00:45],[01:00],[01:15],[01:30],[01:45],[02:00],[02:15],[02:30],[02:45],[03:00],
       [03:15],[03:30],[03:45],[04:00],[04:15],[04:30],[04:45],[05:00],[05:15],[05:30],[05:45],[06:00],
       [06:15],[06:30],[06:45],[07:00],[07:15],[07:30],[07:45],[08:00],[08:15],[08:30],[08:45],[09:00],
       [09:15],[09:30],[09:45],[10:00],[10:15],[10:30],[10:45],[11:00],[11:15],[11:30],[11:45],[12:00],
       [12:15],[12:30],[12:45],[13:00],[13:15],[13:30],[13:45],[14:00],[14:15],[14:30],[14:45],[15:00],
       [15:15],[15:30],[15:45],[16:00],[16:15],[16:30],[16:45],[17:00],[17:15],[17:30],[17:45],[18:00],
       [18:15],[18:30],[18:45],[19:00],[19:15],[19:30],[19:45],[20:00],[20:15],[20:30],[20:45],[21:00],
       [21:15],[21:30],[21:45],[22:00],[22:15],[22:30],[22:45],[23:00],[23:15],[23:30],[23:45],[00:00]
--INTO [Staging].[PivotedData]
FROM(
    SELECT 
        SerialNumber AS [Serial],
        ChannelName AS [Channel],
        CAST(ReadingDate AS DATE) AS [ReadingDate],
        CAST(ReadingDate AS TIME(0)) AS [ReadingTime],
        ChannelValue AS [Value]
    FROM [Staging].[UriData]
    WHERE
        ChannelName IN (SELECT ChannelName FROM Staging.ActiveChannels )
        AND ReadingDate > @_DateFrom AND  ReadingDate <= @_DateTo
        AND SerialNumber = @_SerialNumber
        AND Processed = 0
        AND ChannelName = 'm1'
    ) AS [Raw]
PIVOT
(
    MAX( [Value] ) FOR [ReadingTime] IN( [00:15],[00:30],[00:45],[01:00],[01:15],[01:30],[01:45],[02:00],
                                         [02:15],[02:30],[02:45],[03:00],[03:15],[03:30],[03:45],[04:00],
                                         [04:15],[04:30],[04:45],[05:00],[05:15],[05:30],[05:45],[06:00],
                                         [06:15],[06:30],[06:45],[07:00],[07:15],[07:30],[07:45],[08:00],
                                         [08:15],[08:30],[08:45],[09:00],[09:15],[09:30],[09:45],[10:00],
                                         [10:15],[10:30],[10:45],[11:00],[11:15],[11:30],[11:45],[12:00],
                                         [12:15],[12:30],[12:45],[13:00],[13:15],[13:30],[13:45],[14:00],
                                         [14:15],[14:30],[14:45],[15:00],[15:15],[15:30],[15:45],[16:00],
                                         [16:15],[16:30],[16:45],[17:00],[17:15],[17:30],[17:45],[18:00],
                                         [18:15],[18:30],[18:45],[19:00],[19:15],[19:30],[19:45],[20:00],
                                         [20:15],[20:30],[20:45],[21:00],[21:15],[21:30],[21:45],[22:00],
                                         [22:15],[22:30],[22:45],[23:00],[23:15],[23:30],[23:45],[00:00])
) AS pvt

ORDER BY ReadingDate DESC, Channel, [Serial]

查询产生以下结果:

-----------------------------------------------------------------------------------------------------------------------------
Serial | Channel | ReadingDate | 00:15 | 00:30 | 00:45 | 01:00 | 01:15  <--- ReadingTime --->   23:15 | 23:30 | 23:45 | 00:00
-----------------------------------------------------------------------------------------------------------------------------
2209   |  m1     | 21/09/2018  | NULL  | NULL  | NULL  | NULL  | NULL          <---->           NULL  | NULL  | NULL  | 20586
2209   |  m1     | 20/09/2018  | 20138 | 20140 | 20143 | 20145 | 20148         <---->           20580 | 20582 | 20584 | NULL
-----------------------------------------------------------------------------------------------------------------------------

从查询中可以看出,我请求的值介于两次之间。我希望第二天的午夜出现在“2018-09-20”的行中,因为最后一组读数是在午夜传递的。我在午夜收到 23:45:00 到 23:59:59 的值。所以我有 96 个读数大于“2018-09-20 00:00”且小于或等于“2018-09-21 00:00”。

预期结果是:

-----------------------------------------------------------------------------------------------------------------------------
Serial | Channel | ReadingDate | 00:15 | 00:30 | 00:45 | 01:00 | 01:15  <--- ReadingTime --->   23:15 | 23:30 | 23:45 | 00:00
-----------------------------------------------------------------------------------------------------------------------------
2209   |  m1     | 20/09/2018  | 20138 | 20140 | 20143 | 20145 | 20148         <---->           20580 | 20582 | 20584 | 20586
-----------------------------------------------------------------------------------------------------------------------------

一如既往,感谢您的支持。

【问题讨论】:

  • 你能发一些数据吗
  • sqlfiddle.com/#!18/441a4/6/0 - 你是这个意思吗?
  • @TheOrangeGoblin 你怎么知道哪个是你的基准日期?例如这个样本数据是20/09/2018
  • 这取决于where 子句吗?
  • 是的,因为它必须每天运行一次。我将在 Sproc 中将今天的日期作为变量传递,并在其中添加 1 天。所以我传入例如'2018-09-20 00:00'然后有第二个变量DATEADD(DD,1,'2018-09-20 00:00')。这设置了我必须使用的日期范围。

标签: sql sql-server datetime pivot-table


【解决方案1】:

我会让ReadingDateReadingTime 合并为一列,因为sql-server 中有一个DateTime 数据类型。

如果使用两列会很难在条件下使用。

然后您可以使用CASE WHEN 设置ReadingDate 列检查数据行是今天还是明天,如果是明天,则设置该行中的今天。

在您的数据透视查询之前。

 SELECT [Serial], 
       [Channel],
       [ReadingDate],
       [00:15],[00:30],[00:45],[01:00],[01:15],[01:30],[01:45],[02:00],[02:15],[02:30],[02:45],[03:00],
       [03:15],[03:30],[03:45],[04:00],[04:15],[04:30],[04:45],[05:00],[05:15],[05:30],[05:45],[06:00],
       [06:15],[06:30],[06:45],[07:00],[07:15],[07:30],[07:45],[08:00],[08:15],[08:30],[08:45],[09:00],
       [09:15],[09:30],[09:45],[10:00],[10:15],[10:30],[10:45],[11:00],[11:15],[11:30],[11:45],[12:00],
       [12:15],[12:30],[12:45],[13:00],[13:15],[13:30],[13:45],[14:00],[14:15],[14:30],[14:45],[15:00],
       [15:15],[15:30],[15:45],[16:00],[16:15],[16:30],[16:45],[17:00],[17:15],[17:30],[17:45],[18:00],
       [18:15],[18:30],[18:45],[19:00],[19:15],[19:30],[19:45],[20:00],[20:15],[20:30],[20:45],[21:00],
       [21:15],[21:30],[21:45],[22:00],[22:15],[22:30],[22:45],[23:00],[23:15],[23:30],[23:45],[00:00]
FROM(
    SELECT 
        Serial AS [Serial],
        Channel AS [Channel],
        (CASE WHEN CAST(ReadingDate AS DATE) > CAST(@_DateFrom AS DATE) 
            THEN CAST(@_DateFrom AS DATE) 
            ELSE CAST(ReadingDate AS DATE)
         END)  AS [ReadingDate],
        CAST(ReadingDate AS TIME) AS [ReadingTime],
        Value AS [Value]
    FROM UriData
     WHERE ReadingDate > @_DateFrom  AND ReadingDate <= @_DateTo  AND Serial = '2209'   
    ) AS [Raw]
PIVOT
(
    MAX( [Value] ) FOR [ReadingTime] IN( [00:15],[00:30],[00:45],[01:00],[01:15],[01:30],[01:45],[02:00],
                                         [02:15],[02:30],[02:45],[03:00],[03:15],[03:30],[03:45],[04:00],
                                         [04:15],[04:30],[04:45],[05:00],[05:15],[05:30],[05:45],[06:00],
                                         [06:15],[06:30],[06:45],[07:00],[07:15],[07:30],[07:45],[08:00],
                                         [08:15],[08:30],[08:45],[09:00],[09:15],[09:30],[09:45],[10:00],
                                         [10:15],[10:30],[10:45],[11:00],[11:15],[11:30],[11:45],[12:00],
                                         [12:15],[12:30],[12:45],[13:00],[13:15],[13:30],[13:45],[14:00],
                                         [14:15],[14:30],[14:45],[15:00],[15:15],[15:30],[15:45],[16:00],
                                         [16:15],[16:30],[16:45],[17:00],[17:15],[17:30],[17:45],[18:00],
                                         [18:15],[18:30],[18:45],[19:00],[19:15],[19:30],[19:45],[20:00],
                                         [20:15],[20:30],[20:45],[21:00],[21:15],[21:30],[21:45],[22:00],
                                         [22:15],[22:30],[22:45],[23:00],[23:15],[23:30],[23:45],[00:00])
) AS pvt
ORDER BY ReadingDate DESC, Channel, [Serial]

sqlfiddle

【讨论】:

  • 哇,真的很好用!你在 CASE 语句中说什么在最后增加了价值?我是一名 C# 开发人员,并且努力摆脱困境并进入 SQL。再次感谢,您已经非常慷慨了!
  • 这里有一个关于CASE WHENdocs.microsoft.com/en-us/sql/t-sql/language-elements/…的链接,短CASE WHEN可以在行里写一个if...else
【解决方案2】:

我看到一个&lt;=sign,其中包括上限(第二天)。

也许这可以改变?

AND ReadingDate &gt; @_DateFrom AND ReadingDate &lt;= @_DateTo

【讨论】:

  • 我尝试过投射一个新的日期,但它会将午夜的任何内容视为同一天,而不是明天。
猜你喜欢
  • 1970-01-01
  • 2017-01-07
  • 1970-01-01
  • 2020-07-11
  • 1970-01-01
  • 1970-01-01
  • 2020-04-03
  • 2015-04-03
  • 2013-11-25
相关资源
最近更新 更多