我有一个包含几列(其中有poc_id, user, rw列)的表,并且我正在try 执行一个查询,该查询将返回我:

  • 返回上个月的"Points"总和的值的列,按月份、用户和ID_REW分组.如果上个月没有值,则返回NULL

  • 相同,但来自go 年同月

这将是输出(输入是不包含PREV_MONTHPREV_YEAR列的同一个表,具有与我要查找的内容无关的另一列,我可以忽略它们):

USER ID_REW POINTS POC DATE PREV_MONTH PREV_YEAR
1 1635798105611 10 1 01/01/2021 null null
1 1635798105611 20 1 25/01/2021 null null
1 1635798105611 10 1 05/02/2021 30 null
1 1635798105611 15 1 20/02/2022 null 10
2 1641209778245 50 2 03/02/2021 null null
2 1654058198065 60 2 15/05/2021 null null
2 1654065920033 15 2 25/02/2022 null null
2 1654051152555 10 4 26/02/2022 null null
2 1654051152555 5 4 15/02/2023 null 10
2 1635798105611 25 4 25/02/2023 null null

或者:

INSERT INTO my_table (USER, ID_REW, POINTS, POC, _DATE_, PREV_MONTH, PREV_YEAR)
VALUES
    (1, 1635798105611, 10, 1, '2021-01-01', NULL, NULL),
    (1, 1635798105611, 20, 1, '2021-01-25', NULL, NULL),
    (1, 1635798105611, 10, 1, '2021-02-05', 30, NULL),
    (1, 1635798105611, 15, 1, '2021-02-20', NULL, 10),
    (2, 1641209778245, 50, 2, '2021-02-03', NULL, NULL),
    (2, 1654058198065, 60, 2, '2021-05-15', NULL, NULL),
    (2, 1654065920033, 15, 2, '2022-02-25', NULL, NULL),
    (2, 1654051152555, 10, 4, '2022-02-26', NULL, NULL),
    (2, 1654051152555, 5, 4, '2023-02-15', NULL, 10),
    (2, 1635798105611, 25, 4, '2023-02-25', NULL, NULL);

我try 了类似如下的查询:

WITH cte as 
(
    SELECT
        my columns...,
        ...,
        ....,
        date_buy::date AS _DATE_,
        SUM(POINTS) OVER (PARTITION BY user, id_rew, poc) AS _sum_,
        year(_DATE_)*100 + month(_DATE_) AS ym
    FROM
         etc...
)
SELECT
    USER,
    ID_REW,
    POINTS,
    POC,
    _DATE_,
    LAG(_sum_) OVER (PARTITION BY user, id_rew, poc ORDER BY ym) AS PREV_MONTH,
    LAG(_sum_, 12) OVER (PARTITION BY user, id_rew, poc ORDER BY ym) AS PREV_YEAR
FROM
    cte
GROUP BY
    1, 2, 3, 4, 5;

但我有几个错误,例如,在年-月202205到202203中,它返回值202203,而它应该返回NULL(因为在202204中没有购买)

我已经try 了一些我在互联网上看到的东西(我在那里了解到滞后函数的存在),也使用了一些变量,但到目前为止,试图复制我所看到的东西还没有成功.欢迎任何帮助

推荐答案

如何使用基于连接的基本逻辑来执行此操作,我还包括了"当前合计月份",只是为了判断这些数字是否有意义:

WITH my_table(USER, ID_REW, POINTS, POC, _DATE_) as (
    SELECT * FROM VALUES
        (1, 1635798105611, 10, 1, '2021-01-01'::date),
        (1, 1635798105611, 20, 1, '2021-01-25'::date),
        (1, 1635798105611, 10, 1, '2021-02-05'::date),
        (1, 1635798105611, 15, 1, '2021-02-20'::date),
        (2, 1641209778245, 50, 2, '2021-02-03'::date),
        (2, 1654058198065, 60, 2, '2021-05-15'::date),
        (2, 1654065920033, 15, 2, '2022-02-25'::date),
        (2, 1654051152555, 10, 4, '2022-02-26'::date),
        (2, 1654051152555, 5, 4, '2023-02-15'::date),
        (2, 1635798105611, 25, 4, '2023-02-25'::date)
), enriched as (
    select *
        ,date_trunc(month, _date_) as sum_month
    from my_table
), summed as (
    select 
        user 
        ,id_rew
        ,poc
        ,sum_month
        ,dateadd('month', 1, sum_month) as next_month
        ,dateadd('year', 1, sum_month) as next_year
        ,sum(points) as s_points
    from enriched
    group by 1,2,3,4
)
select a.*
    ,b.s_points as current_months_points
    ,c.s_points as prev_months_points
    ,d.s_points as prev_year_points  
from enriched as a
join summed as b 
    on a.user = b.user and a.id_rew = b.id_rew and a.poc = b.poc and a.sum_month = b.sum_month
left join summed as c
    on a.user = c.user and a.id_rew = c.id_rew and a.poc = c.poc and a.sum_month = c.next_month
left join summed as d
    on a.user = d.user and a.id_rew = d.id_rew and a.poc = d.poc and a.sum_month = d.next_year
order by 1,2,4,5
    

enter image description here

执行情况:

但如果它在我的数据库上,我会将前一个的联接重新组织到CTE中,以降低所有成本:

WITH my_table(USER, ID_REW, POINTS, POC, _DATE_) as (
    SELECT * FROM VALUES
        (1, 1635798105611, 10, 1, '2021-01-01'::date),
        (1, 1635798105611, 20, 1, '2021-01-25'::date),
        (1, 1635798105611, 10, 1, '2021-02-05'::date),
        (1, 1635798105611, 15, 1, '2021-02-20'::date),
        (2, 1641209778245, 50, 2, '2021-02-03'::date),
        (2, 1654058198065, 60, 2, '2021-05-15'::date),
        (2, 1654065920033, 15, 2, '2022-02-25'::date),
        (2, 1654051152555, 10, 4, '2022-02-26'::date),
        (2, 1654051152555, 5, 4, '2023-02-15'::date),
        (2, 1635798105611, 25, 4, '2023-02-25'::date)
), enriched as (
    select *
        ,date_trunc(month, _date_) as sum_month
    from my_table
), summed as (
    select 
        user 
        ,id_rew
        ,poc
        ,sum_month
        ,dateadd('month', 1, sum_month) as next_month
        ,dateadd('year', 1, sum_month) as next_year
        ,sum(points) as s_points
    from enriched
    group by 1,2,3,4
), gather as (
    select 
        a.* exclude(next_month, next_year, s_points)
        ,b.s_points as prev_months_points
        ,c.s_points as prev_year_points  
    from summed as a
    left join summed as b 
        on a.user = b.user 
            and a.id_rew = b.id_rew 
            and a.poc = b.poc 
            and a.sum_month = b.next_month
    left join summed as c
        on a.user = c.user 
            and a.id_rew = c.id_rew 
            and a.poc = c.poc 
            and a.sum_month = c.next_year
)
select a.* exclude(sum_month)
    ,b.prev_months_points
    ,b.prev_year_points
from enriched as a
join gather as b 
    on a.user = b.user and a.id_rew = b.id_rew and a.poc = b.poc and a.sum_month = b.sum_month

order by 1,2,4,5

enter image description here

Sql相关问答推荐

LAG函数通过丢弃空值返回前一行

通过 Select 值的顺序进行排序ClickHouse

返回找到的最小和最大row_number()spark SQL

直接加法(1+1)与聚合函数SUM(1+1)的区别是什么

DBeaver将过程中的属性列表转换为字符串

用VB.NET在Dapper中实现MS Access数据库顺序透视

如何使用Clickhouse的COUNT聚合返回所有列,但GROUP BY是这些列的子集

从重复值中获取最新值

通过UPDATE SELECT更新表时出现问题

将二维数组的第一个和第二个元素取消嵌套到两个一维数组中

将 jsonb 数组中的对象取消嵌套到单独的行中

Grafana SQL 模板变量(值、文本)

如何判断小数点后千位是否不为0

如何修复初学者 SQL INNER JOIN 查询错误

计算不同模式的时间跨度

使用 SQL 计算一年中任意 3 个月期间的总成本

PostgreSQL - 从同一张表中获取值

雅典娜弄错了操作顺序

如何在 SQL Server 中将 -13422.8450 舍入到 -13422.84

使用 R 遍历 SQL 查询,每次替换一个变量