lui*_*ati 4 sql postgresql timestamp gaps-and-islands
鉴于下表:
CREATE TABLE channel1m (
ts TIMESTAMP WITHOUT TIME ZONE NOT NULL,
itemId BIGINT,
value BIGINT
)
Run Code Online (Sandbox Code Playgroud)
在其中一排可被插入每分钟,每的itemId,如下所示:
ts itemId value
2012-12-03 15:29:00 100 1
2012-12-03 15:30:00 100 2
2012-12-03 15:30:00 101 0
2012-12-03 15:32:00 100 1
2012-12-03 15:32:00 101 1
Run Code Online (Sandbox Code Playgroud)
我找不到一种方法(不创建额外的表)来编写填充时间间隔的查询(例如,对于itemId 101为15:29:00,对于两个项目为15:31:00),返回NULL值.
预期的结果集将是:
ts itemId value
2012-12-03 15:29:00 100 1
2012-12-03 15:29:00 101 NULL
2012-12-03 15:30:00 100 2
2012-12-03 15:30:00 101 0
2012-12-03 15:31:00 100 NULL
2012-12-03 15:31:00 101 NULL
2012-12-03 15:32:00 100 1
2012-12-03 15:32:00 101 1
Run Code Online (Sandbox Code Playgroud)
我发现解决方案有一个单独的时间表和完整的时间戳系列,但我更愿意单独在查询中解决这个问题.这可能吗?
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path = tmp;
DROP TABLE IF EXISTS channel1m CASCADE;
CREATE TABLE channel1m (
zts TIMESTAMP WITHOUT TIME ZONE NOT NULL,
zitemid BIGINT,
zvalue BIGINT
);
-- in which a row may be inserted each minute, per zitemid, as follows:
INSERT INTO channel1m(zts, zitemid, zvalue) VALUES
('2012-12-03 15:29:00', 100, 1)
,('2012-12-03 15:30:00', 100, 2)
,('2012-12-03 15:30:00', 101, 0)
,('2012-12-03 15:32:00', 100, 1)
,('2012-12-03 15:32:00', 101, 1)
;
-- CTE to the rescue!!!
WITH cal AS (
WITH mm AS (
SELECT MIN(xx.zts) AS minmin, MAX(xx.zts) AS maxmax
FROM channel1m xx)
SELECT generate_series(mm.minmin , mm.maxmax , '1 min'::interval) AS stamp
FROM mm
)
, ite AS (
SELECT DISTINCT zitemid AS zitemid
FROM channel1m
)
SELECT cal.stamp
, ite.zitemid
, tab.zvalue
FROM cal
JOIN ite ON 1=1 -- Note: this is a cartesian product of the {time,id} -domains
LEFT JOIN channel1m tab ON tab.zts = cal.stamp AND tab.zitemid = ite.zitemid
ORDER BY stamp ASC
;
Run Code Online (Sandbox Code Playgroud)
输出:
NOTICE: drop cascades to table tmp.channel1m
DROP SCHEMA
CREATE SCHEMA
SET
NOTICE: table "channel1m" does not exist, skipping
DROP TABLE
CREATE TABLE
INSERT 0 5
stamp | zitemid | zvalue
---------------------+---------+--------
2012-12-03 15:29:00 | 101 |
2012-12-03 15:29:00 | 100 | 1
2012-12-03 15:30:00 | 100 | 2
2012-12-03 15:30:00 | 101 | 0
2012-12-03 15:31:00 | 100 |
2012-12-03 15:31:00 | 101 |
2012-12-03 15:32:00 | 100 | 1
2012-12-03 15:32:00 | 101 | 1
(8 rows)
Run Code Online (Sandbox Code Playgroud)
您将需要:table with all itemId,以及一个包含所有必需日期的(伪)表.
你可能有所有不同的表itemId.让我们来称呼它item_table.
带有日期的伪表generate_series('start_date','end_date', interval '1 minute').细节在这里.
查询:
SELECT gs.ts, it.itemId, ch1m.value
FROM item_table it
CROSS JOIN generate_series('start_date','end_date', interval '1 minute') gs(ts)
LEFT JOIN channel1m ch1m ON it.itemId = ch1m.itemId
AND gs.ts = ch1m.ts
Run Code Online (Sandbox Code Playgroud)
替换'start_date','end_date'为所需的值或从子查询中获取它们.
这个查询:
1)通过构建所有项目时间对 CROSS JOIN
2)获取value通道LEFT JOIN
| 归档时间: |
|
| 查看次数: |
4256 次 |
| 最近记录: |