5

我正在编写一个脚本来分析 SQL Server 2008 数据库上数千个表中包含的一些数据。

为简单起见,可以将表分解为 4-8 个半相关表的组。半相关是指它们是同一项目的数据集合,但它们没有任何实际的 SQL 关系。每个表都包含一个日期时间戳(datetime2数据类型)、值(可以是bitintfloat取决于特定项目)以及当前不感兴趣的一些其他列。日期时间戳在几秒钟内每 15 分钟(一刻钟)设置一次;然而,并不是所有的数据都被精确地同时记录下来......

例如:

表格1:

TIMESTAMP                 VALUE
2014-11-27 07:15:00.390      1
2014-11-27 07:30:00.390      0
2014-11-27 07:45:00.373      0
2014-11-27 08:00:00.327      0

表 2:

TIMESTAMP                 VALUE
2014-11-19 08:00:07.880      0
2014-11-19 08:15:06.867      0.0979999974370003
2014-11-19 08:30:08.593      0.0979999974370003
2014-11-19 08:45:07.397      0.0979999974370003

表3

TIMESTAMP                 VALUE
2014-11-27 07:15:00.390        0
2014-11-27 07:30:00.390        0
2014-11-27 07:45:00.373        1
2014-11-27 08:00:00.327        1

如您所见,并非所有表格都以相同的 Quarterly 开头TIMESTAMP。基本上,我所追求的是一个查询,它将每 15 分钟间隔返回 3 个表中的每一个的 VALUE,从 3 个表中最早TIMESTAMP的一个开始。对于给出的示例,我想从 2014-11-27 07:15 开始(不关心秒数......因此,需要允许时间戳为 +- 1 分钟左右)。当没有特定 TIMESTAMP 的记录时,为该值返回 NULL 是可以的。因此,我列出的示例的查询将返回如下内容:

TIMESTAMP                 VALUE1   VALUE2             VALUE3
2014-11-27 07:15           1    NULL                  0
2014-11-27 07:30           0    NULL                  0
2014-11-27 07:45           0    NULL                  1
2014-11-27 08:00           0    NULL                  1
...
2014-11-19 08:00           0         0                        1
2014-11-19 08:15           0         0.0979999974370003       0
2014-11-19 08:30           0         0.0979999974370003       0
2014-11-19 08:45           0         0.0979999974370003       0

我希望这是有道理的。任何帮助/指针/指导将不胜感激。

4

3 回答 3

1

利用Full Outer Join

SELECT COALESCE(a.[TIMESTAMP], b.[TIMESTAMP], c.[TIMESTAMP]) [TIMESTAMP],
       Isnull(Max(a.VALUE), 0)                               VALUE1,
       Max(b.VALUE)                                          VALUE2,
       Isnull(Max(c.VALUE), 0)                               VALUE3
FROM   TABLE1 a
       FULL OUTER JOIN TABLE2 b
                    ON CONVERT(SMALLDATETIME, a.[TIMESTAMP]) = CONVERT(SMALLDATETIME, b.[TIMESTAMP])
       FULL OUTER JOIN TABLE3 c
                    ON CONVERT(SMALLDATETIME, a.[TIMESTAMP]) = CONVERT(SMALLDATETIME, c.[TIMESTAMP])
GROUP  BY COALESCE(a.[TIMESTAMP], b.[TIMESTAMP], c.[TIMESTAMP])
ORDER  BY [TIMESTAMP] DESC 
于 2014-12-19T17:47:49.670 回答
0

这是 NoDisplayName 的答案的更新版本,可以满足您的要求。它适用于 SQL 2012,但您可以将 DATETIMEFROMPARTS 函数替换为一系列其他函数以获得相同的结果。

;WITH 
NewT1 as (
SELECT DATETimeFROMPARTS( DATEPART(year,Timestamp) , DATEPART(month,timestamp) , datepart(day,timestamp),datepart(hour,timestamp), datepart(minute,timestamp),0,0 ) as TimeStamp, Value
FROM Table1),
NewT2 as (
SELECT DATETimeFROMPARTS( DATEPART(year,Timestamp) , DATEPART(month,timestamp) , datepart(day,timestamp),datepart(hour,timestamp), datepart(minute,timestamp),0,0 ) as TimeStamp, Value
FROM Table2),
NewT3 as (
SELECT DATETimeFROMPARTS( DATEPART(year,Timestamp) , DATEPART(month,timestamp) , datepart(day,timestamp),datepart(hour,timestamp), datepart(minute,timestamp),0,0 ) as TimeStamp, Value
FROM Table3)
SELECT COALESCE(a.[TIMESTAMP], b.[TIMESTAMP], c.[TIMESTAMP]) [TIMESTAMPs],
       Isnull(Max(a.VALUE), 0)                            VALUE1,
       Isnull(Max(b.VALUE), 0)                                       VALUE2,
       Isnull(Max(c.VALUE), 0)                                       VALUE3
FROM   NewT1 a
       FULL OUTER JOIN NewT2 b
                    ON a.[TIMESTAMP] = b.[TIMESTAMP]
       FULL OUTER JOIN TABLE3 c
                    ON a.[TIMESTAMP] = b.[TIMESTAMP]
GROUP  BY COALESCE(a.[TIMESTAMP], b.[TIMESTAMP], c.[TIMESTAMP])
ORDER  BY [TIMESTAMPs] 
于 2014-12-19T18:12:16.813 回答
0

我要做的第一件事是将时间戳标准化为分钟。您可以通过更新现有列来做到这一点

UPDATE TABLENAME
  SET TIMESTAMP = dateadd(minute,datediff(minute,0,TIMESTAMP),0)

或在新列中

ALTER TABLE TABLENAME ADD COLUMN NORMTIME DATETIME;

UPDATE TABLENAME
  SET NORMTIME = dateadd(minute,datediff(minute,0,TIMESTAMP),0)

有关地板日期的详细信息,请参阅这篇文章:在 SQL 服务器中设置日期


下一步是创建一个表,其中包含您希望看到的所有时间戳(标准化)——即每 15 个——每行一个。对于我的示例,让我们将此表称为 TIME_PERIOD 和列 EVENT_TIME(您可以随意称呼它)。

有很多方法可以使这样的表递归 CTE,ROW_NUMBER(),甚至是蛮力。我把那部分留给你。


现在问题是简单的选择左连接和有效值的过滤器,如下所示:

SELECT TP.EVENT_TIME, a.VALUE as VALUE1, b.VALUE as VALUE2, c.VALUE as VALUE3
FROM  TIME_PERIOD TP
LEFT JOIN TABLE1 a ON a.[TIMESTAMP] = TP.EVENT_TIME
LEFT JOIN TABLE2 b ON b.[TIMESTAMP] = TP.EVENT_TIME
LEFT JOIN TABLE3 c ON c.[TIMESTAMP] = TP.EVENT_TIME
WHERE COALESCE(a.[TIMESTAMP], b.[TIMESTAMP], c.[TIMESTAMP]) is not null
ORDER  BY TP.EVENT_TIME DESC 

如果它们是不同的类型,则 where 可能会变得更复杂,因此您始终可以使用它(它不如 coalesce 但总是有效):

WHERE a.[TIMESTAMP] IS NOT NULL OR
      b.[TIMESTAMP] IS NOT NULL OR
      c.[TIMESTAMP] IS NOT NULL
于 2014-12-19T18:05:03.487 回答