Red*_*ter 310
此解决方案不使用循环,过程或临时表.子查询生成最近10,000天的日期,并且可以根据需要延伸到后退或前进.
select a.Date
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) ) DAY as 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
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 d
) a
where a.Date between '2010-01-20' and '2010-01-24'
Run Code Online (Sandbox Code Playgroud)
输出:
Date
----------
2010-01-24
2010-01-23
2010-01-22
2010-01-21
2010-01-20
Run Code Online (Sandbox Code Playgroud)
关于绩效的说明
在这里测试,性能出奇的好:上面的查询需要0.0009秒.
如果我们扩展子查询以生成约.100,000个数字(因此大约274年的日期),它运行0.0458秒.
顺便提一下,这是一种非常便携的技术,可以对大多数数据库进行微调.
Sté*_*ane 31
以下是使用视图的另一种变体:
CREATE VIEW digits AS
SELECT 0 AS digit 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;
CREATE VIEW numbers AS
SELECT
ones.digit + tens.digit * 10 + hundreds.digit * 100 + thousands.digit * 1000 AS number
FROM
digits as ones,
digits as tens,
digits as hundreds,
digits as thousands;
CREATE VIEW dates AS
SELECT
SUBDATE(CURRENT_DATE(), number) AS date
FROM
numbers;
Run Code Online (Sandbox Code Playgroud)
然后你可以简单地做(看看它有多优雅?):
SELECT
date
FROM
dates
WHERE
date BETWEEN '2010-01-20' AND '2010-01-24'
ORDER BY
date
Run Code Online (Sandbox Code Playgroud)
更新
值得注意的是,您只能从当前日期开始生成过去的日期.如果要生成任何类型的日期范围(过去,将来和之间),则必须使用此视图:
CREATE VIEW dates AS
SELECT
SUBDATE(CURRENT_DATE(), number) AS date
FROM
numbers
UNION ALL
SELECT
ADDDATE(CURRENT_DATE(), number + 1) AS date
FROM
numbers;
Run Code Online (Sandbox Code Playgroud)
Dmi*_*sev 21
接受的答案对PostgreSQL不起作用(语法错误在"a"或附近).
在PostgreSQL中执行此操作的方法是使用generate_series
函数,即:
SELECT day::date
FROM generate_series('2010-01-20', '2010-01-24', INTERVAL '1 day') day;
day
------------
2010-01-20
2010-01-21
2010-01-22
2010-01-23
2010-01-24
(5 rows)
Run Code Online (Sandbox Code Playgroud)
Jos*_*hua 13
使用递归公用表表达式(CTE),您可以生成日期列表,然后从中进行选择.显然你通常不想创建三百万个日期,所以这只是说明了可能性.您可以简单地限制CTE内的日期范围,并使用CTE省略select语句中的where子句.
with [dates] as (
select convert(datetime, '1753-01-01') as [date] --start
union all
select dateadd(day, 1, [date])
from [dates]
where [date] < '9999-12-31' --end
)
select [date]
from [dates]
where [date] between '2013-01-01' and '2013-12-31'
option (maxrecursion 0)
Run Code Online (Sandbox Code Playgroud)
在Microsoft SQL Server 2005上,生成所有可能日期的CTE列表时间为1:08.生成一百年不到一秒钟.
小智 7
MSSQL查询
select datetable.Date
from (
select DATEADD(day,-(a.a + (10 * b.a) + (100 * c.a)),getdate()) AS 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
) datetable
where datetable.Date between '2014-01-20' and '2014-01-24'
order by datetable.Date DESC
Run Code Online (Sandbox Code Playgroud)
产量
Date
-----
2014-01-23 12:35:25.250
2014-01-22 12:35:25.250
2014-01-21 12:35:25.250
2014-01-20 12:35:25.250
Run Code Online (Sandbox Code Playgroud)
在没有循环/游标的情况下执行此操作的老式解决方案是创建一个NUMBERS
表,该表具有单个 Integer 列,其值从 1 开始。
CREATE TABLE `example`.`numbers` (
`id` int(10) unsigned NOT NULL auto_increment,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)
您需要在表中填充足够的记录以满足您的需求:
INSERT INTO NUMBERS (id) VALUES (NULL);
Run Code Online (Sandbox Code Playgroud)
获得NUMBERS
表格后,您可以使用:
SELECT x.start_date + INTERVAL n.id-1 DAY
FROM NUMBERS n
JOIN (SELECT STR_TO_DATE('2010-01-20', '%Y-%m-%d') AS start_date
FROM DUAL) x
WHERE x.start_date + INTERVAL n.id-1 DAY <= '2010-01-24'
Run Code Online (Sandbox Code Playgroud)
绝对的低技术解决方案是:
SELECT STR_TO_DATE('2010-01-20', '%Y-%m-%d')
FROM DUAL
UNION ALL
SELECT STR_TO_DATE('2010-01-21', '%Y-%m-%d')
FROM DUAL
UNION ALL
SELECT STR_TO_DATE('2010-01-22', '%Y-%m-%d')
FROM DUAL
UNION ALL
SELECT STR_TO_DATE('2010-01-23', '%Y-%m-%d')
FROM DUAL
UNION ALL
SELECT STR_TO_DATE('2010-01-24', '%Y-%m-%d')
FROM DUAL
Run Code Online (Sandbox Code Playgroud)
生成日期或数字列表以便左连接。您这样做是为了查看数据中存在间隙的位置,因为您左连接到序列数据列表 - 空值将使存在间隙的位置变得明显。
归档时间: |
|
查看次数: |
113620 次 |
最近记录: |