【问题标题】:PostgreSQL , Select from 2 tables, but only the latest element from table 2PostgreSQL ,从 2 个表中选择,但仅从表 2 中选择最新的元素
【发布时间】:2009-11-09 20:19:53
【问题描述】:

嘿,我在 PostgreSql 中有 2 个表:

1 - documents: id, title
2 - updates: id, document_id, date

还有一些数据:

文件:

| 1 | Test Title |

更新:

| 1 | 1 | 2006-01-01 |
| 2 | 1 | 2007-01-01 |
| 3 | 1 | 2008-01-01 |

所以所有更新都指向同一个文档,但所有更新的日期都不同。

我要做的是从文档表中进行选择,但还包括基于日期的最新更新。

这样的查询应该是什么样子?这是我目前拥有的,但我列出了所有更新,而不是我需要的最新更新:

SELECT * FROM documents,updates WHERE documents.id=1 AND documents.id=updates.document_id ORDER BY date

包括;我在查询中需要这个的原因是我想从更新模板中按日期排序!

编辑:这个脚本很重 简化,所以我应该能够 创建一个返回任意数字的查询 结果,但包括最新的 更新日期。我正在考虑使用 内连接或左连接什么的 就这样!?

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    使用PostgreSQL 扩展DISTINCT ON:

    SELECT  DISTINCT ON (documents.id) *
    FROM    document
    JOIN    updates
    ON      updates.document_id = document_id
    ORDER BY
            documents.id, updates.date DESC
    

    这将从ORDER BY 顺序中的每个document.id 集群中取出第一行。

    要检查的测试脚本:

    SELECT  DISTINCT ON (documents.id) *
    FROM    (
            VALUES
            (1, 'Test Title'),
            (2, 'Test Title 2')
            ) documents (id, title)
    JOIN    (
            VALUES
            (1, 1, '2006-01-01'::DATE),
            (2, 1, '2007-01-01'::DATE),
            (3, 1, '2008-01-01'::DATE),
            (4, 2, '2009-01-01'::DATE),
            (5, 2, '2010-01-01'::DATE)
            ) updates (id, document_id, date)
    ON      updates.document_id = documents.id
    ORDER BY
            documents.id, updates.date DESC
    

    【讨论】:

    • 可以统计文件吗?
    • @holden321 当然是。请将其作为几个问题发布,并附上您的设置和要求。
    【解决方案2】:

    您可以创建一个派生表,其中每个 document_id 仅包含最近的“更新”记录,然后针对该表加入“文档”:

    SELECT d.id, d.title, u.update_id, u."date"
    FROM documents d
    LEFT JOIN
    -- JOIN "documents" against the most recent update per document_id
    (
    SELECT recent.document_id, id AS update_id, recent."date"
    FROM updates
    INNER JOIN
    (SELECT document_id, MAX("date") AS "date" FROM updates GROUP BY 1) recent
    ON updates.document_id = recent.document_id
    WHERE
      updates."date" = recent."date"
    ) u
    ON d.id = u.document_id;
    

    这将处理“未更新”的文档,如下所示:

    pg=> select * from documents;
     id | title 
    ----+-------
      1 | foo
      2 | bar
      3 | baz
    (3 rows)
    
    pg=> select * from updates;
     id | document_id |    date    
    ----+-------------+------------
      1 |           1 | 2009-10-30
      2 |           1 | 2009-11-04
      3 |           1 | 2009-11-07
      4 |           2 | 2009-11-09
    (4 rows)
    
    pg=> SELECT d.id ...
     id | title | update_id |    date    
    ----+-------+-----------+------------
      1 | foo   |         3 | 2009-11-07
      2 | bar   |         4 | 2009-11-09
      3 | baz   |           | 
    (3 rows)
    

    【讨论】:

      【解决方案3】:
      select *
      from documents
      left join updates
        on updates.document_id=documents.id
        and updates.date=(select max(date) from updates where document_id=documents.id)
      where documents.id=?;
      

      它比以前的答案有一些优势:

      • document_id 只能写在一个方便的地方;
      • 您可以省略 where,您将获得所有文档及其最新更新的表格;
      • 您可以使用更广泛的选择标准,例如where documents.id in (1,2,3)

      您也可以避免使用 group by 进行子选择,但您必须在 group by 子句中列出文档的所有字段:

      select documents.*, max(date) as max_date
        from documents
        left join updates on documents.id=document_id
        where documents.id=1
        group by documents.id, title;
      

      【讨论】:

        【解决方案4】:

        从我的头顶:

        ORDER BY date DESC LIMIT 1
        

        如果你真的只想要 id 1 你可以使用这个查询:

        SELECT * FROM documents,updates 
            WHERE documents.id=1 AND updates.document_id=1 
            ORDER BY date DESC LIMIT 1
        

        http://www.postgresql.org/docs/8.4/interactive/queries-limit.html

        【讨论】:

          【解决方案5】:

          这也应该有效

          SELECT * FROM documents, updates 
              WHERE documents.id=1 AND updates.document_id=1
              AND updates.date = (SELECT MAX (date) From updates) 
          

          【讨论】:

          • 不,正如目前所写的那样,这行不通。无论文档如何,您的子查询都会从整个更新表中返回最近的“日期”,因此只有当您选择的documents.id 恰好在最近的更新日期更新时才会产生结果。
          • 你是对的。子查询应读取 SELECT MAX (date) From updates where id = 1)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-01-17
          • 1970-01-01
          • 1970-01-01
          • 2022-01-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多