
已知价格会随着时间发生变化,想要求得每款产品的每个价格的起始时间,示例数据如下。 需要注意的是当价格发生变动后又恢复了原价的话,起始日期需重新计算,如 item_id 为 2 ,price 为 399 的数据,就产出了两条起始时间。只能编写 SQL 实现
input: item_id price dt 1 100 2020-01-01 1 100 2020-01-02 1 120 2020-01-03 2 399 2020-01-01 2 399 2020-01-02 2 399 2020-01-03 2 499 2020-01-04 2 399 2020-01-05 output: item_id price start_date end_date 1 100 2020-01-01 2020-01-02 1 120 2020-01-03 2020-01-03 2 399 2020-01-01 2020-01-03 2 499 2020-01-04 2020-01-04 2 399 2020-01-05 9999-12-31 感谢大佬们的提示,我把我写的sql贴出来,有问题还请指正。
select item_id,price,start_date,case when start_date!=end_date then end_date else '9999-12-31' end as end_date from ( select item_id,price,min(dt) start_date,max(dt) end_date from ( select item_id, price, dt, row_number() over(partition by item_id,price order by dt) rk, date_sub(dt,row_number() over(partition by item_id,price order by dt)) res from price_info )a group by item_id,price,res )b 1 saluton 2022-12-06 22:39:34 +08:00 可以搜一下 [SQL 连续签到天数] 的题,看起来差不多的思路。 |
2 F281M6Dh8DXpD1g2 2022-12-06 23:11:51 +08:00 via iPhone 按价格分组之后连续的日期有啥特征? 连续的日期减去一个自增的数列是一个定值,按这个分组不就完了 |
5 tinywhale 2022-12-07 07:56:32 +08:00 这个是典型的 gaps and islands 类型问题,技巧是要先分组,然后每个组的 min/max date 就是开始和结束日期。 |
6 AutumnVerse 2022-12-07 08:24:33 +08:00 via Android select price,max (dt),min (dt) from xxx group price |
7 cau1iflower 2022-12-07 08:46:23 +08:00 ChatGPT 了解一下 |
8 cau1iflower 2022-12-07 08:48:53 +08:00 @cau1iflower ``` SELECT item_id, price, -- 如果当前价格和前一个价格不同,那么这个价格的起始时间就是当前日期。 -- 否则,起始时间就是前一个价格的起始时间。 CASE WHEN price != LAG(price) OVER (PARTITION BY item_id ORDER BY date) THEN date ELSE LAG(start_date) OVER (PARTITION BY item_id ORDER BY date) END AS start_date, -- 如果当前价格和后一个价格不同,那么这个价格的结束时间就是后一个价格的起始时间。 -- 否则,这个价格的结束时间就是 NULL 。 CASE WHEN price != LEAD(price) OVER (PARTITION BY item_id ORDER BY date) THEN LEAD(start_date) OVER (PARTITION BY item_id ORDER BY date) ELSE NULL END AS end_date FROM prices ``` |
9 wloverine OP @jiangwei2222 直接 group by 的话就会造成 item_id 为 2 ,price 为 399 的起始日期变成了 2020-01-01~2020-01-05 ,这显然是不合理的 |
10 wxf666 2022-12-07 11:02:49 +08:00 |
12 wxf666 2022-12-07 13:53:34 +08:00 @SbloodyS 数据库新手问下,现在基本都不用 PostgreSQL 、MySQL 、SQL Server 、Oracle 、SQLite 这些数据库了是吗? |
13 blue7wings 2022-12-07 14:10:54 +08:00 以下是 OpenAI 给出的答案,不知道对不对,你可以参考一下:) Here is one possible solution using SQL: ```sql SELECT item_id, price, MIN(dt) as start_date, (SELECT MIN(dt) FROM prices AS p2 WHERE p2.item_id = p1.item_id AND p2.price != p1.price AND p2.dt > p1.dt) as end_date FROM prices as p1 GROUP BY item_id, price ``` This query groups the prices for each item_id and price combination and finds the minimum dt (the start date) for each group. Then, for each group, it uses a subquery to find the minimum dt for the next price change (the end date) for the same item_id. If there is no next price change, the end date is set to the maximum date value. You can use this query as a starting point and modify it to fit your specific needs. |
14 wxf666 2022-12-09 13:25:23 +08:00 @SbloodyS 突然很好奇,如果 Clickhouse 支持直接用别名的话,下面这种 SQL 会计算成什么? ```sql SELECT IF(id % 2, LEAD(a) OVER (...), LAG(a) OVER (...)) AS a FROM ... ``` 大意:若 id 为奇数,则取下一行的值,否则取上一行的值 |
16 wxf666 2022-12-09 14:53:30 +08:00 |