我正在尝试破解一个看起来很简单的SQL问题:
temp.test
。内容:
DROP TABLE IF EXISTS temp.test;
CREATE TEMP TABLE temp.test (
row_id INTEGER IDENTITY (1, 1),
id VARCHAR,
start_ts TIMESTAMP,
end_ts TIMESTAMP,
level1 VARCHAR,
level2 VARCHAR
);
INSERT INTO temp.test (id, start_ts, end_ts, level1, level2) VALUES
('a', '1970-01-01 00:00:00.000000', '2017-12-31 23:59:59.999999', 'ABC1', 'ABC2'),
('a', '2018-01-01 00:00:00.000000', '2018-12-31 23:59:59.999999', 'DEF1', 'DEF2'),
('a', '2019-01-01 00:00:00.000000', '2019-12-31 23:59:59.999999', 'ABC1', 'GHI2'),
('a', '2020-01-01 00:00:00.000000', '2020-12-31 23:59:59.999999', 'ABC1', 'JKL2');
我基本上想结束:
-- Desired output
('a', '1970-01-01 00:00:00.000000', '2017-12-31 23:59:59.999999', 'ABC1'),
('a', '2018-01-01 00:00:00.000000', '2018-12-31 23:59:59.999999', 'DEF1'),
('a', '2019-01-01 00:00:00.000000', '2020-12-31 23:59:59.999999', 'ABC1'),
意味着,我想要列level1
的最低版本集合。请注意,第三行和第四行将重复,但是在这种情况下,我们将获得min(start_ts)
和max(end_ts)
来计算版本。
这是我尝试过的方法,但我失败了...
-- Wrong
SELECT
id,
min(start_ts) AS start_ts,
max(end_ts) AS end_ts,
level1
FROM temp.test
GROUP BY id, level1
ORDER BY 2;
-- Wrong
SELECT DISTINCT
id,
FIRST_VALUE(start_ts) OVER(PARTITION BY id, level1 ORDER BY start_ts) AS start_ts,
LAST_VALUE(end_ts) OVER(PARTITION BY id, level1 ORDER BY start_ts) AS end_ts,
level1
FROM temp.test
ORDER BY 2;
必须有某种神奇的方式来获得我需要的输出。您有什么建议?
注意:我正在使用Snowflake,但这只是标准的SQL。
答案 0 :(得分:2)
这是一个孤岛问题。在这种情况下,我将使用row_number()
方法:
SELECT id, level1,
MIN(start_ts) as start_ts, MAX(end_ts) as end_ts
FROM (SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY start_ts) as seqnum_i,
ROW_NUMBER() OVER (PARTITION BY id, level1 ORDER BY start_ts) as seqnum_il,
FROM temp.test t
) t
GROUP BY id, level1, (seqnum_i - seqnum_il);
请注意,这假设开始和结束时间戳记之间没有间隙。
这是如何工作的,目前尚不清楚。我通常建议您只盯着子查询的结果。通常很明显,两个行号之间的差异标识了要聚合的组。