SQL根据日期时间从多个表中进行选择

mko*_*ker 5 sql sql-server join datetime2

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

为简单起见,表格可以分为4-8个半相关表格.通过半关联,我的意思是它们是同一项的数据集合,但它们没有任何实际的SQL关系.每个表由一个日期-时间戳(的datetime2数据类型),值(可以是一个bit,int或float根据特定的项目),和当前不感兴趣的一些其它列.日期时间标记在几秒钟内每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
Run Code Online (Sandbox Code Playgroud)

TABLE2:

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
Run Code Online (Sandbox Code Playgroud)

表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
Run Code Online (Sandbox Code Playgroud)

如您所见,并非所有表都以相同的季度开始TIMESTAMP.基本上,我所追求的是一个查询,它将从3个表中最早的每个15分钟间隔返回3个表中每个表的VALUE 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
Run Code Online (Sandbox Code Playgroud)

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

Hog*_*gan 0

我要做的第一件事是将时间戳标准化为分钟。您可以通过更新现有列来完成此操作

UPDATE TABLENAME
  SET TIMESTAMP = dateadd(minute,datediff(minute,0,TIMESTAMP),0)
Run Code Online (Sandbox Code Playgroud)

或在新列中

ALTER TABLE TABLENAME ADD COLUMN NORMTIME DATETIME;

UPDATE TABLENAME
  SET NORMTIME = dateadd(minute,datediff(minute,0,TIMESTAMP),0)
Run Code Online (Sandbox Code Playgroud)

有关保留日期的详细信息,请参阅此帖子:Floor a date in SQL Server


下一步是创建一个表,其中包含您期望看到的所有时间戳(标准化)——即每 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 
Run Code Online (Sandbox Code Playgroud)

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

WHERE a.[TIMESTAMP] IS NOT NULL OR
      b.[TIMESTAMP] IS NOT NULL OR
      c.[TIMESTAMP] IS NOT NULL
Run Code Online (Sandbox Code Playgroud)