查询以获取具有最接近时间戳值的记录以获取两列的唯一组合
Query to get records with closest timestamp values for unique combination of two columns
+-------+----------------------+----------+------------------+
| 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 |
+-------+----------------------+----------+------------------+
假设我有一个 table (PostgreSQL),就像上面的 bookshelf_configuration
。如果给我一个 ISBN 和一个时间戳,我希望能够为 isbn
和 book_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)
.
执行此操作
有一个叫做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
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
。详细解释:
- Select first row in each GROUP BY group?
根据基数和值频率,可能会有更快的查询样式:
- Optimize GROUP BY query to retrieve latest record per user
无论哪种方式,(isbn, book_container_id, update_time DESC)
上的 multicolumn index 是快速处理非平凡大小的表的关键。排序顺序应与查询匹配(或者是完全反转)。如果将 NULLS LAST
添加到查询中,请将其也添加到索引中。
旁白:最好对所有日期/时间常量使用 ISO 8601 格式,因为这对于任何区域设置或日期样式设置都是明确的。相关:
- PostgreSQL: between with datetime
+-------+----------------------+----------+------------------+
| 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 |
+-------+----------------------+----------+------------------+
假设我有一个 table (PostgreSQL),就像上面的 bookshelf_configuration
。如果给我一个 ISBN 和一个时间戳,我希望能够为 isbn
和 book_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)
.
有一个叫做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
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
。详细解释:
- Select first row in each GROUP BY group?
根据基数和值频率,可能会有更快的查询样式:
- Optimize GROUP BY query to retrieve latest record per user
无论哪种方式,(isbn, book_container_id, update_time DESC)
上的 multicolumn index 是快速处理非平凡大小的表的关键。排序顺序应与查询匹配(或者是完全反转)。如果将 NULLS LAST
添加到查询中,请将其也添加到索引中。
旁白:最好对所有日期/时间常量使用 ISO 8601 格式,因为这对于任何区域设置或日期样式设置都是明确的。相关:
- PostgreSQL: between with datetime