英文:
How to put an incremental counter for each group in SQL (Snowflake)
问题
我有以下表格 - 基本上是一组起始日期和结束日期之间的产品及其价格。起始日期和结束日期按升序排列。
product start end price
A 08/04/2022 12/04/2022 29
A 13/04/2022 12/05/2022 45
A 13/05/2022 25/12/2022 45
A 26/12/2022 16/05/2023 29
A 17/05/2023 23/05/2023 29
A 24/05/2023 31/12/9999 49
我想要的是一个计数器,它基本上检查价格是否与前一行(对于特定产品)不同。如果是,将计数器增加1,否则将计数器值复制到上面。输出应该如下所示:
product start end price counter
A 08/04/2022 12/04/2022 29 1
A 13/04/2022 12/05/2022 45 2
A 13/05/2022 25/12/2022 45 2
A 26/12/2022 16/05/2023 29 3
A 17/05/2023 23/05/2023 29 3
A 24/05/2023 31/12/9999 49 4
任何帮助将不胜感激。谢谢。
英文:
I have the following table - essentially a product and its price between a set of start and end dates. The start and end dates are sorted in ascending order.
product start end price
A 08/04/2022 12/04/2022 29
A 13/04/2022 12/05/2022 45
A 13/05/2022 25/12/2022 45
A 26/12/2022 16/05/2023 29
A 17/05/2023 23/05/2023 29
A 24/05/2023 31/12/9999 49
What I want is to have a counter that essentially checks if the price has changed from its previous row (for a particular product). If yes, increment the counter by 1, else copy the counter value from above.
Output should look like below:
product start end price counter
A 08/04/2022 12/04/2022 29 1
A 13/04/2022 12/05/2022 45 2
A 13/05/2022 25/12/2022 45 2
A 26/12/2022 16/05/2023 29 3
A 17/05/2023 23/05/2023 29 3
A 24/05/2023 31/12/9999 49 4
Any help will be highly appreciated. Thanks.
答案1
得分: 3
Snowflake支持CONDITIONAL_CHANGE_EVENT窗口函数,专为此设计:
对于窗口分区内的每一行,当当前行中参数expr1的值与前一行中的expr1的值不同时,返回一个窗口事件编号。 窗口事件编号从0开始,每次增加1,以表示在该窗口内迄今为止的更改次数。
SELECT *, CONDITIONAL_CHANGE_EVENT(price)
OVER(PARTITION BY product ORDER BY start_) + 1 AS counter
FROM tab
ORDER BY product, start_;
对于输入表:
ALTER SESSION SET DATE_INPUT_FORMAT = 'DD/MM/YYYY';
CREATE OR REPLACE TABLE tab(product TEXT, start_ DATE, end_ DATE, price INT)
AS
SELECT 'A','08/04/2022','12/04/2022', 29 UNION ALL
SELECT 'A','13/04/2022','12/05/2022', 45 UNION ALL
SELECT 'A','13/05/2022','25/12/2022', 45 UNION ALL
SELECT 'A','26/12/2022','16/05/2023', 29 UNION ALL
SELECT 'A','17/05/2023','23/05/2023', 29 UNION ALL
SELECT 'A','24/05/2023','31/12/9999', 49;
输出:
英文:
Snowflake supports CONDITIONAL_CHANGE_EVENT windowed function that is exactly designed for it:
> Returns a window event number for each row within a window partition when the value of the argument expr1 in the current row is different from the value of expr1 in the previous row. The window event number starts from 0 and is incremented by 1 to indicate the number of changes so far within that window.
SELECT *, CONDITIONAL_CHANGE_EVENT(price)
OVER(PARTITION BY product ORDER BY start_) + 1 AS counter
FROM tab
ORDER BY product, start_;
For input table:
ALTER SESSION SET DATE_INPUT_FORMAT = 'DD/MM/YYYY';
CREATE OR REPLACE TABLE tab(product TEXT, start_ DATE, end_ DATE, price INT)
AS
SELECT 'A','08/04/2022','12/04/2022', 29 UNION ALL
SELECT 'A','13/04/2022','12/05/2022', 45 UNION ALL
SELECT 'A','13/05/2022','25/12/2022', 45 UNION ALL
SELECT 'A','26/12/2022','16/05/2023', 29 UNION ALL
SELECT 'A','17/05/2023','23/05/2023', 29 UNION ALL
SELECT 'A','24/05/2023','31/12/9999', 49;
Output:
答案2
得分: 2
以下是您要翻译的代码部分:
您可以使用一个运行总和来检查价格的前一个值是否不等于产品的当前价格值的标志:
with t as
(
select *,
case
when lag(price, 1, price) over (partition by product order by start_dt) <> price
then 1 else 0
end as flag
from tbl
)
select product, start_dt, end_dt, price,
(sum(flag) over (partition by product order by start_dt) + 1) counter
from t
demo(在SQL Server上)
英文:
You could use a running sum on a flag that checks if the previous value of the price is not equal to the current price value of a product:
with t as
(
select *,
case
when lag(price, 1, price) over (partition by product order by start_dt) <> price
then 1 else 0
end as flag
from tbl
)
select product, start_dt, end_dt, price,
(sum(flag) over (partition by product order by start_dt) + 1) counter
from t
demo (on SQL server)
答案3
得分: 0
使用 rank() over
。
select *, rank() over(order by price) counter
from mytable
rank() over
- 这个窗口子句将从1开始,并且如果下一个值相同,那么它将继续而不将1添加到排名值。
因此,计数器的值将为1、2、2、3、4,因为第2和第3个值相同。
英文:
Use rank() over
.
select *, rank() over(order by price) counter
from mytable
rank() over
- this window clause will start from 1, and if the next value is same, then it will continue and not add 1 to the rank value.
So, counter values will be 1,2,2,3,4 because 2nd and 3rd values are same.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论