小编典典

SQL:找到公式来生成日期,只是试图理解它

sql

因此,对于如何快速有效地生成日期列表而没有循环等问题,我现在已经在多个答案中看到了它。该公式有效,我已经将其复制,测试,使用了,等等。问题是,我只是不了解其背后的数学原理。我讨厌使用我不了解的东西,我觉得自己是A)作弊,B)之后会为遇到的问题做好准备。

无论如何,这是我正在谈论的公式:

set @start_date = '2015-9-20';
set @end_date = '2016-9-20';

select @start_date + interval ((a.a) + (10 * b.a) + (100 * c.a)) day as this_date
from 
(select 0 as a
union all select 1
union all select 2
union all select 3
union all select 4
union all select 5
union all select 6
union all select 7
union all select 8
union all select 9) as a cross join
(select 0 as a
union all select 1
union all select 2
union all select 3
union all select 4
union all select 5
union all select 6
union all select 7
union all select 8
union all select 9) as b cross join
(select 0 as a
union all select 1
union all select 2
union all select 3
union all select 4
union all select 5
union all select 6
union all select 7
union all select 8
union all select 9) as c;

快速说明:start_date / end_date东西只适合我。我最终将把它变成一个使用这两个值来生成日期范围的过程,这里的值只是我解决此问题时的测试值。

因此,让我们从我真正理解的部分开始,然后继续进行其他所有工作。

1)并集实际上是创建3个10行的表,其整数值为0-9。

2)3个表在没有指定where子句的情况下连接在一起,这意味着它是笛卡尔连接,并且行数呈指数增长(10 x 10 x 10 = 1000)。

3)日期值将以等于INTERVAL语句旁边括号内的值的天数间隔递增。

4)数学模式反映了笛卡尔联接。第一个表的每个值乘以1,第二个表乘以10,第三个表乘以100。

我不明白的是:数学本身。通过某种方式,通过将这些数字加在一起,结果是一个间隔,最终使日期的值增加了1000天。我只是想真正理解为什么它行之有效,除了模式之外,还包括真正的数学,程序化原因。

提前非常感谢。


阅读 172

收藏
2021-05-16

共1个答案

小编典典

您尝试做的是在两个日期之间生成一个范围。

通常,您可以使用循环forwhile但不能与普通选择一起使用,并且需要存储过程。

当您意识到选择生成编号从0到999。

因此,您可以生成将近3年的日期。您得到的是:

@start_date + 1 day
@start_date + 2 days
@start_date + 3 days
...
@start_date +  999 days

但是您的查询错过了哪里

WHERE @start_date + interval ((a.a) + (10 * b.a) + (100 * c.a)) <= @end_date

假设您要创建小时数范围,则需要添加另一个表格以将范围增加到0.. 9999并将时间间隔设置为hours

DATE_ADD(@start_date, INTERVAL (a.a) + (10 * b.a) + (100 * c.a) + (1000 * d.a) HOUR)

要得到:

@start_date + 1 hour
@start_date + 2 hours
@start_date + 3 hours
...
@start_date +  9999 hours

其他说明

所有联合创建一个派生表。该代码等效于您创建具有1000行的表并从中进行选择。

SELECT *
FROM table1000

1000 rows return

然后,您可以使用该表上的每个值和常量@start_date来更改每一行

现在您有了一个列表,其中包含1000天的起始日期 @start_date

最后,您使用@end_date进行过滤,以删除大于所需日期的日期。

2021-05-16