SQL - 日期范围内缺少时间
SQL - missing time in date range
我在 table 中有数据显示点火 true
或 false
|--------------------------------------|
| date | ignition |
|---------------------------|----------|
|2019-06-03 10:15:00.000000 | false |
|---------------------------|----------|
|2019-06-03 10:30:00.000000 | false |
|---------------------------|----------|
|2019-06-03 11:30:00.000000 | true |
|---------------------------|----------|
|2019-06-03 11:45:00.000000 | false |
|---------------------------|----------|
|2019-06-03 11:55:00.000000 | false |
|---------------------------|----------|
我写了 SQL 显示日期期间点火状态的查询
SELECT min(date) as date_from, max(date) as date_to, ignition
FROM (SELECT date,
ignition,
row_number() over (order by date) as seqnum,
row_number() over (partition by ignition order by date) as seqnum_s
FROM table_data
WHERE date >= '2019-06-01T21:00:00.000Z' AND date <= '2019-06-09T20:59:59.999Z'
) as raw_data
GROUP BY (seqnum - seqnum_s), ignition
ORDER BY min(date);
查询结果:
|---------------------------|----------------------------|----------|
| date_from | date_to | ignition |
|---------------------------|----------------------------|----------|
|2019-06-03 10:15:00.000000 | 2019-06-03 10:30:00.000000 | false |
|---------------------------|----------------------------|----------|
|2019-06-03 11:30:00.000000 | 2019-06-03 11:30:00.000000 | true |
|---------------------------|----------------------------|----------|
|2019-06-03 11:45:00.000000 | 2019-06-03 11:55:00.000000 | false |
|---------------------------|----------------------------|----------|
但结果中缺少从 10:30
到 11:30
的日期和从 11:30
到 11:45
的日期。我应该得到这个:
|---------------------------|----------------------------|----------|
| date_from | date_to | ignition |
|---------------------------|----------------------------|----------|
|2019-06-03 10:15:00.000000 | 2019-06-03 11:30:00.000000 | false |
|---------------------------|----------------------------|----------|
|2019-06-03 11:30:00.000000 | 2019-06-03 11:45:00.000000 | true |
|---------------------------|----------------------------|----------|
|2019-06-03 11:45:00.000000 | 2019-06-03 11:55:00.000000 | false |
|---------------------------|----------------------------|----------|
问题是在聚合成一个块时(例如 false 后面的 5 行)他只查看 false 的最后一行来确定块的结束时间,而不是接下来的第一行(第一个是真)
OK,就用window函数lead
得到下一行的值date_from
,然后把这个值设置到当前行的date_to
,SQL如下:
select
date_from,
case when lead(date_from,1) over(order by date_from) is null then date_to else lead(date_from,1) over(order by date_from) end as date_to,
ignition
from (
SELECT min(date) as date_from, max(date) as date_to, ignition
FROM (SELECT date,
ignition,
row_number() over (order by date) as seqnum,
row_number() over (partition by ignition order by date) as seqnum_s
FROM table_data
WHERE date >= '2019-06-01T21:00:00.000Z' AND date <= '2019-06-09T20:59:59.999Z'
) as raw_data
GROUP BY (seqnum - seqnum_s), ignition
ORDER BY min(date)
) tmp;
date_from | date_to | ignition
---------------------+---------------------+----------
2019-06-03 10:15:00 | 2019-06-03 11:30:00 | f
2019-06-03 11:30:00 | 2019-06-03 11:45:00 | t
2019-06-03 11:45:00 | 2019-06-03 11:55:00 | f
(3 rows)
更简单的表达方式是:
SELECT min(date) as date_from,
lead(min(date)) over (order by min(date)) as date_to,
ignition
FROM (SELECT d.*,
row_number() over (order by date) as seqnum,
row_number() over (partition by ignition order by date) as seqnum_s
FROM table_data d
WHERE date >= '2019-06-01T21:00:00.000Z' AND date < '2019-06-09T21:00:00Z'
) as raw_data
GROUP BY (seqnum - seqnum_s), ignition
ORDER BY min(date)
我在 table 中有数据显示点火 true
或 false
|--------------------------------------|
| date | ignition |
|---------------------------|----------|
|2019-06-03 10:15:00.000000 | false |
|---------------------------|----------|
|2019-06-03 10:30:00.000000 | false |
|---------------------------|----------|
|2019-06-03 11:30:00.000000 | true |
|---------------------------|----------|
|2019-06-03 11:45:00.000000 | false |
|---------------------------|----------|
|2019-06-03 11:55:00.000000 | false |
|---------------------------|----------|
我写了 SQL 显示日期期间点火状态的查询
SELECT min(date) as date_from, max(date) as date_to, ignition
FROM (SELECT date,
ignition,
row_number() over (order by date) as seqnum,
row_number() over (partition by ignition order by date) as seqnum_s
FROM table_data
WHERE date >= '2019-06-01T21:00:00.000Z' AND date <= '2019-06-09T20:59:59.999Z'
) as raw_data
GROUP BY (seqnum - seqnum_s), ignition
ORDER BY min(date);
查询结果:
|---------------------------|----------------------------|----------|
| date_from | date_to | ignition |
|---------------------------|----------------------------|----------|
|2019-06-03 10:15:00.000000 | 2019-06-03 10:30:00.000000 | false |
|---------------------------|----------------------------|----------|
|2019-06-03 11:30:00.000000 | 2019-06-03 11:30:00.000000 | true |
|---------------------------|----------------------------|----------|
|2019-06-03 11:45:00.000000 | 2019-06-03 11:55:00.000000 | false |
|---------------------------|----------------------------|----------|
但结果中缺少从 10:30
到 11:30
的日期和从 11:30
到 11:45
的日期。我应该得到这个:
|---------------------------|----------------------------|----------|
| date_from | date_to | ignition |
|---------------------------|----------------------------|----------|
|2019-06-03 10:15:00.000000 | 2019-06-03 11:30:00.000000 | false |
|---------------------------|----------------------------|----------|
|2019-06-03 11:30:00.000000 | 2019-06-03 11:45:00.000000 | true |
|---------------------------|----------------------------|----------|
|2019-06-03 11:45:00.000000 | 2019-06-03 11:55:00.000000 | false |
|---------------------------|----------------------------|----------|
问题是在聚合成一个块时(例如 false 后面的 5 行)他只查看 false 的最后一行来确定块的结束时间,而不是接下来的第一行(第一个是真)
OK,就用window函数lead
得到下一行的值date_from
,然后把这个值设置到当前行的date_to
,SQL如下:
select
date_from,
case when lead(date_from,1) over(order by date_from) is null then date_to else lead(date_from,1) over(order by date_from) end as date_to,
ignition
from (
SELECT min(date) as date_from, max(date) as date_to, ignition
FROM (SELECT date,
ignition,
row_number() over (order by date) as seqnum,
row_number() over (partition by ignition order by date) as seqnum_s
FROM table_data
WHERE date >= '2019-06-01T21:00:00.000Z' AND date <= '2019-06-09T20:59:59.999Z'
) as raw_data
GROUP BY (seqnum - seqnum_s), ignition
ORDER BY min(date)
) tmp;
date_from | date_to | ignition
---------------------+---------------------+----------
2019-06-03 10:15:00 | 2019-06-03 11:30:00 | f
2019-06-03 11:30:00 | 2019-06-03 11:45:00 | t
2019-06-03 11:45:00 | 2019-06-03 11:55:00 | f
(3 rows)
更简单的表达方式是:
SELECT min(date) as date_from,
lead(min(date)) over (order by min(date)) as date_to,
ignition
FROM (SELECT d.*,
row_number() over (order by date) as seqnum,
row_number() over (partition by ignition order by date) as seqnum_s
FROM table_data d
WHERE date >= '2019-06-01T21:00:00.000Z' AND date < '2019-06-09T21:00:00Z'
) as raw_data
GROUP BY (seqnum - seqnum_s), ignition
ORDER BY min(date)