【问题标题】:PostgreSQL Pivot by Last DatePostgreSQL 按最后日期透视
【发布时间】:2021-01-01 19:23:09
【问题描述】:

我需要像这张表一样从 Source 制作一个 PIVOT 表

FactID  UserID  Date    Product QTY
1         11    01/01/2020  A   600
2         11    02/01/2020  A   400
3         11    03/01/2020  B   500
4         11    04/01/2020  B   200
6         22    06/01/2020  A   1000
7         22    07/01/2020  A   200
8         22    08/01/2020  B   300
9         22    09/01/2020  B   100

需要像这样的数据透视,其中产品数量是 Last Date

的数量
UserID  A   B
11      400 200
22      200 100

我尝试 PostgreSQL

Select 
        UserID,
        MAX(CASE WHEN Product='A' THEN 'QTY' END) AS 'A',
        MAX(CASE WHEN Product='B' THEN 'QTY' END) AS 'B'
FROM table
GROUP BY UserID

结果

UserID  A   B
11     600  500
22     1000 300

我的意思是我得到的是最大数量而不是最大日期的结果! 我需要添加什么才能在最大(最后)日期之前获得结果??

【问题讨论】:

    标签: sql postgresql pivot pivot-table


    【解决方案1】:

    Postgres 没有“first”和“last”聚合函数。这样做的一种方法(没有子查询)使用数组:

    select userid,
           (array_agg(qty order by date desc) filter (where product = 'A'))[1] as a,
           (array_agg(qty order by date desc) filter (where product = 'B'))[1] as b
    from tab
    group by userid;
    

    另一种方法使用select distinctfirst_value()

    select distinct userid,
           first_value(qty) over (partition by userid order by product = 'A' desc, date desc) as a,
           first_value(qty) over (partition by userid order by product = 'B' desc, date desc) as b
    from tab;
    

    不过,使用适当的索引,distinct on 可能是最快的方法:

    select userid,
           max(qty) filter (where product = 'A') as a,
           max(qty) filter (where product = 'B') as b
    from (select distinct on (userid, product) t.*
          from tab t
          order by userid, product, date desc
         ) t
    group by userid;
    

    特别是,这可以使用userid, product, date desc) 上的索引。如果给定用户有多个日期,则性能的改进将最为显着。

    【讨论】:

      【解决方案2】:

      您可以使用 DENSE_RANK() 窗口函数,以便在应用条件聚合之前按每个产品的最后日期和用户 ID 进行过滤,例如

      SELECT UserID, 
             MAX(CASE WHEN Product='A' THEN QTY END) AS "A",
             MAX(CASE WHEN Product='B' THEN QTY END) AS "B"
        FROM
        (
          SELECT t.*, DENSE_RANK() OVER (PARTITION BY Product,UserID ORDER BY Date DESC) AS rn
            FROM tab t     
        ) q
       WHERE rn = 1 
       GROUP BY UserID
      

      Demo

      假设所有日期值都是不同的(日期没有关联

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-09
        • 2019-08-16
        • 2019-06-27
        • 1970-01-01
        • 2022-01-03
        • 2020-03-07
        • 1970-01-01
        相关资源
        最近更新 更多