【问题标题】:按最大日期选择值
【发布时间】:2022-01-03 12:43:36
【问题描述】:

我在 PostgreSQL 数据库中有一个表,其中包含如下数据:

id  customer_id   item       value     timestamp

 1  001           price       1000     11/1/2021
 2  001           price       1500     11/2/2021
 3  001           condition   good     11/3/2021
 4  002           condition   bad      11/4/2021
 5  002           condition   good     11/5/2021
 6  002           price       1000     11/6/2021
 7  001           condition   good     11/7/2021
 8  001           price       1400     11/8/2021
 9  002           price       1500     11/9/2021
10  001           condition    ok      11/10/2021
11  002           price       1600     11/11/2021
12  002           price       1550     11/12/2021

从这个表中,我想按日期查询最新的值,并将其转换为如下表。

customer_id   price   condition
   001        1400      ok
   002        1550     good

为了得到这种表,我尝试使用下面的查询,但是当数据太多时它不能很好地工作。 (像MinMax对文字和数字的操作)

我在 pgAdmin 4 中对此进行了测试:

SELECT customer_id,
MAX (Case WHEN item='price' THEN value END) price,
MAX (Case WHEN item='condition' THEN value END) condition

FROM table_name GROUP BY customer_id

我想查询最新日期更新数据的值。

【问题讨论】:

    标签: sql postgresql greatest-n-per-group


    【解决方案1】:
     SELECT X.CUSTOMER_ID,X.PRICE,X.CONDITION
     FROM
     (
          SELECT A.CUSTOMER_ID,A.PRICE,A.CONDITION,
           ROW_NUMBER()OVER(PARTITION BY A.CUSTOMER_ID ORDER BY A.TIMESTAMP DESC)XCOL
      FROM YOUR_TABLE A
     )X WHERE X.XCOL=1 
    

    如果以上适合你,你可以试试吗

    【讨论】:

    • 我可以知道 X 和 A 是干什么用的吗? table_name 应该放在哪里?
    • 已修改。希望,现在更清楚了
    • @Yan: XAtable aliases。但是这个查询并不能满足您的要求。
    【解决方案2】:

    您的关系设计可能会得到改进。在同一列中混合不同类型的数据是一种反模式。

    虽然坚持给定的设置,但 DISTINCT ONFULL OUTER JOIN 的两个子查询可以完成这项工作:

    SELECT customer_id, p.value AS price, c.value AS condition
    FROM  (
       SELECT DISTINCT ON (customer_id)
              customer_id, value
       FROM   tbl
       WHERE  item = 'condition'
       ORDER  BY customer_id, timestamp DESC
       ) c
    FULL JOIN (
       SELECT DISTINCT ON (customer_id)
              customer_id, value
       FROM   tbl
       WHERE  item = 'price'
       ORDER  BY customer_id, timestamp DESC
       ) p USING (customer_id)
    

    db小提琴here

    见:

    这假设 timestamp 被定义为 NOT NULL,或者你会想要 NULLS LAST

    根据未公开的基数和价值分布,可能会有(很多)更快的查询变体。
    如果有一个 customer 表具有不同的 customer_id,则(更快)查询样式成为可能。

    这些部分的、多列的索引在任何情况下都非常适合使其快速:

    CREATE INDEX tbl_condition_special_idx ON tbl (customer_id, timestamp DESC, value) WHERE item = 'condition';
    CREATE INDEX tbl_price_special_idx     ON tbl (customer_id, timestamp DESC, value) WHERE item = 'price';
    

    见:

    【讨论】:

    • 它有效。谢谢你。顺便说一句,是否有任何更短的查询,因为在示例问题中我只在 Item 列下使用了两个值?实际上,我可能需要查询才能创建多个列。
    • @Yan:根据精确表定义、基数、数据分布和customer表的存在,可能会更简单/更优雅/(很多)更快查询...如果您需要,请开始一个新问题并按照此处的说明提供所有内容:stackoverflow.com/tags/postgresql-performance/info 您始终可以链接到此问题以获取上下文,也可以在此处发表评论以引起我的注意。
    • 感谢您的帮助。我将创建一个包含更多信息的问题,包括您的指示。
    • 我添加了一个包含更多信息的新问题。我希望你能得到一些想法来帮助我。如果您有空,请查看此question。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2022-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 2012-04-15
    • 2012-12-24
    相关资源
    最近更新 更多