【问题标题】:Query to get records with closest timestamp values for unique combination of two columns查询以获取具有最接近时间戳值的记录,以获得两列的唯一组合
【发布时间】:2015-12-02 20:14:15
【问题描述】:
+-------+----------------------+----------+------------------+
| isbn  | book_container_id    | shelf_id |   update_time    |
+-------+----------------------+----------+------------------+
|   555 |                    6 | shelf100 | 11/15/2015 19:10 |
|   123 |                    1 | shelf1   | 11/28/2015 8:00  |
|   555 |                    4 | shelf5   | 11/28/2015 9:10  |
|   212 |                    2 | shelf2   | 11/29/2015 8:10  |
|   555 |                    6 | shelf9   | 11/30/2015 22:10 |
|   321 |                    8 | shelf7   | 11/30/2015 8:10  |
|   555 |                    4 | shelf33  | 12/1/2015 7:00   |
+-------+----------------------+----------+------------------+

假设我有一个类似上面的表 (PostgreSQL),名为 bookshelf_configuration。如果给我一个 ISBN 和一个时间戳,我希望能够为 isbnbook_container_id 的每个唯一组合找到最接近(仅之前)的记录。

所以如果我正在查看isbn'555',时间戳为'12/1/2015 7:00',我应该返回:

+-------+----------------------+----------+------------------+
| isbn  | book_container_id    | shelf_id |   update_time    |
+-------+----------------------+----------+------------------+
|   555 |                    6 | shelf9   | 11/30/2015 22:10 |
|   555 |                    4 | shelf33  | 12/1/2015 7:00   |
+-------+----------------------+----------+------------------+

我的 SQL 知识非常基础。如果我只需要考虑 isbn,我就有一个可以使用的查询,但我需要一些帮助来了解如何为 (isbn, book_container_id) 组合执行此操作。

【问题讨论】:

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


    【解决方案1】:

    DISTINCT ON的典型用例:

    SELECT DISTINCT ON (book_container_id)
           isbn, book_container_id, shelf_id, update_time 
    FROM   bookshelf_configuration
    WHERE  isbn = 555
    AND    update_time <= '2015-12-01 07:00'  -- ISO 8601 format
    ORDER  BY book_container_id, update_time DESC;
    

    假设update_time 定义为NOT NULL,或者你必须添加NULLS LAST。详细解释:

    根据基数和值频率,可能会有更快的查询样式:

    无论哪种方式,(isbn, book_container_id, update_time DESC) 上的 multicolumn index 是使非平凡大小的表快速实现这一点的关键。排序顺序应该与查询匹配(或者是完全反转)。如果您将 NULLS LAST 添加到查询中,请将其添加到索引中。

    另外:最好对所有日期/时间常数使用 ISO 8601 格式,因为这对于任何语言环境或日期样式设置都是明确的。相关:

    【讨论】:

    • 我试过了;不幸的是,Redshift 似乎不支持 DISTINCT ON (我应该提到这一点,但我没有意识到它会有所作为)。我选择了 JamieD77 解决方案的一个版本,但我选择这个答案是因为完整的解释和有关这两种解决方案的信息的链接等。感谢他们帮助我更好地理解事情的链接!回复:ISO 8601 建议,我们确实对日期字符串使用 ISO 8601 格式 - 我最初在 excel 中写出了我的示例表,所以我认为它们在那里搞砸了(或者只是用户错误......)
    【解决方案2】:

    这里有一个叫做Row_Number 的东西可以帮助你。

    Select * 
    From (
        Select *,
               row_number() OVER (partition by isbn, book_container_id order by update_time desc) rn
        From   bookshelf_configuration
        Where  isbn = 555 and update_time <= '12/1/2015 7:00'   
    ) q 
    Where q.rn = 1
    

    【讨论】:

    • 谢谢!这确实对我有用-但我觉得我应该选择其他答案,因为链接包含更多信息并与其他方法进行比较等。我确实要感谢您-这让我昨天畅通无阻并能够继续前进:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 2015-09-10
    • 1970-01-01
    相关资源
    最近更新 更多