SQL LAG() 函数与带有条件的情况

huangapple go评论106阅读模式
英文:

SQL LAG() function with condition where

问题

我有我的表格如下:

WITH 
my_table (user_id, date, event_name, value) AS (
    VALUES 
    (1,'2021-10-01', 'level', 5),
    (1,'2021-10-03', 'purchase', null),
    (1,'2021-10-05', 'purchase', null),
    (2,'2021-10-02', 'level', 10),
    (2,'2021-10-03', 'purchase', null)
) 
SELECT *
FROM my_table

我只想为每个user_id的每次purchase之前添加一个列,显示最后一次level的值。期望的表格应如下所示:

|user_id|date      |event_name|value|level_achieved|
|-------|----------|----------|-----|--------------|
|1      |2021-10-01|level     |5    |              |
|1      |2021-10-03|purchase  |null |5             |
|1      |2021-10-05|purchase  |null |5             |
|2      |2021-10-02|level     |10   |              |
|2      |2021-10-03|purchase  |null |10            |

感谢您的帮助!

英文:

I have my table like this:

    WITH 
my_table (user_id, date, event_name, value) AS (
    values 
    (1,'2021-10-01', 'level', 5),
    (1,'2021-10-03', 'purchase', null),
    (1,'2021-10-05', 'purchase', null),
    (2,'2021-10-02', 'level', 10),
    (2,'2021-10-03', 'purchase', null)
) 
SELECT *
FROM my_table
user_id date event_name level
1 2021-10-01 level 5
1 2021-10-03 purchase
1 2021-10-05 purchase
2 2021-10-02 level 10
2 2021-10-03 purchase

All I want is to add column with the last level achieved before every purchase for every user_id.
Desired table should look like this

user_id date event_name level level_achieved
1 2021-10-01 level 5
1 2021-10-03 purchase 5
1 2021-10-05 purchase 5
2 2021-10-02 level 10
2 2021-10-03 purchase 10

Thanks for helping me!

答案1

得分: 3

假设级别不会下降,您可以只使用 max,它将忽略 null 值:

SELECT *,
    if(value is null, max(value) over(partition by user_id order by date)) level_achieved
FROM my_table;

输出:

user_id date event_name value level_achieved
1 2021-10-01 level 5 NULL
1 2021-10-03 purchase NULL 5
1 2021-10-05 purchase NULL 5
2 2021-10-02 level 10 NULL
2 2021-10-03 purchase NULL 10

或者使用带有 ignore nulls 选项的 last_value

SELECT *,
    if(value is null, last_value(value) IGNORE NULLS over(partition by user_id order by date)) level_achieved
FROM my_table;
英文:

Assuming that level can't go down you can use just max which will ignore null's:

SELECT *,
    if(value is null, max(value) over(partition by user_id order by date)) level_achieved
FROM my_table;

Output:

user_id date event_name value level_achieved
1 2021-10-01 level 5 NULL
1 2021-10-03 purchase NULL 5
1 2021-10-05 purchase NULL 5
2 2021-10-02 level 10 NULL
2 2021-10-03 purchase NULL 10

Or using last_value with ignore nulls option:

SELECT *,
    if(value is null, last_value(value) IGNORE NULLS over(partition by user_id order by date)) level_achieved
FROM my_table;

答案2

得分: 1

我建议您创建一个包含以下内容的子查询:

user_id、level、date as date_start、lead(date) over(partition by user_id order by date asc) as date_end
(其中 level 不为 null)

您将获得以下结构:

user_id、level、date_start、date_end

接下来,您可以与以下内容进行连接:

my_table ON my_table.date >= sub_query.date_start 
    AND my_table.date < sub_query.date_end
    AND my_table.user_id = sub_query.user_id

这样,您可以轻松获取特定日期范围的级别。

祝您好运。

英文:

I would advise you to create a subquery with the following:

user_id, level, date as date_start, lead(date) over(partition by user_id order by date asc) as date_end
(where level is not null)

You will get a structure like:

user_id, level, date_start, date_end

Next you can join with:

        my_table ON my_table.date &gt;= sub_query.date_start 
    AND my_table.date &lt; sub_query.date_end
AND my_table.user_id = sub_query.user_id

With this you can easily get the level for that specific date range.

Good luck

huangapple
  • 本文由 发表于 2023年8月5日 01:41:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76838119.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定