SQL JOIN table with a date range
说,我有一个包含C列和N行的表。 我想生成一个select语句,表示该表的"连接",数据范围包括M天。 结果集应该有C + 1列(最后一个是日期)和NXM行。
澄清事情的简单例子:
鉴于下表A:
1 2 3 4 | SELECT * FROM A; avalue | --------+ "a" | |
日期范围从2012年10月10日到12日,我想要以下结果集:
1 2 3 4 5 | avalue | DATE --------+------- "a" | 2012-10-10 "a" | 2012-10-11 "a" | 2012-10-12 |
(这是我在最终计算任何一天的库存水平时需要的垫脚石,给定起始值和增量)
Postgres的方法很简单:
1 2 3 4 5 | SELECT t.*, g.day::DATE FROM tbl t CROSS JOIN generate_series(TIMESTAMP '2012-10-10' , TIMESTAMP '2012-10-12' , INTERVAL '1 day') AS g(DAY); |
准确生成所请求的输出。
- 生成PostgreSQL中两个日期之间的时间序列
对于任意日期,请将
1 2 3 4 5 6 7 8 | SELECT * FROM tbl t CROSS JOIN ( VALUES (DATE '2012-08-13') -- explicit type in 1st row , ('2012-09-05') , ('2012-10-10') ) g(DAY); |
如果日期表中包含的日期多于您感兴趣的日期,那么请执行此操作
1 | SELECT a.avalue, b.date FROM a, b WHERE b.date BETWEEN '2012-10-10' AND '2012-10-12' |
另外明智的是,如果日期表只包含您感兴趣的日期,则笛卡尔联接将实现此目的:
1 | SELECT * FROM a,b; |
你真的有两个选择,你想要做什么。
如果你的RDBMS支持它(我知道SQL Server有,但我不知道其他任何),你可以创建一个表值函数,它接受一个日期范围并返回该范围内所有离散日期的结果集。您可以在表和函数之间进行笛卡尔连接。
您可以创建日期值的静态表,然后在两个表之间进行笛卡尔连接。
第二个选项将表现更好,特别是如果您正在处理大日期范围,但是,该解决方案将无法处理任意日期范围。但是,你应该知道你的最短约会,随着时间的推移,你总是可以在你的桌子上添加更多日期。
对于MySQL
架构/数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | CREATE TABLE someTable ( someCol VARCHAR(8) NOT NULL ); INSERT INTO someTable VALUES ('a'); CREATE TABLE calendar ( calDate datetime NOT NULL, isBus bit ); ALTER TABLE calendar ADD CONSTRAINT PK_calendar PRIMARY KEY (calDate); INSERT INTO calendar VALUES ('2012-10-10', 1); INSERT INTO calendar VALUES ('2012-10-11', 1); INSERT INTO calendar VALUES ('2012-10-12', 1); |
查询:
1 | SELECT s.someCol, c.calDate FROM someTable s, calendar c; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | DECLARE @Date1 datetime = '20121010', @Date2 datetime = '20121012'; WITH Dates AS ( SELECT @Date1 AS [DATE] UNION ALL SELECT dateadd(dd, 1, D.[DATE]) AS [DATE] FROM Dates AS D WHERE D.[DATE] <= DATEADD(dd, -1, @Date2) ) SELECT A.value, D.[DATE] FROM Dates AS D CROSS JOIN A |
我对你的M桌不是很清楚。如果你有这样一个带有日期的表(M),那么在交叉连接之后会带来结果。
1 | SELECT C.*, M.date FROM C CROSS JOIN M |