gpt4 book ai didi

sql - 按 order_num 字段查找下一个连续行

转载 作者:搜寻专家 更新时间:2023-10-30 23:35:09 24 4
gpt4 key购买 nike

我在 Postgres 9.5 数据库中有 4 个表用于向具有以下表结构的客户发送通知:

通知

id    name     
--------------
111 notice1
112 notice2
113 notice3

notice_documents - 单个通知可以包含多个文档,其中 order_num 递增。

id    notice_id   name   order_num    
----------------------------------
211 111 doc1 1
212 111 doc2 2
213 111 doc2 3
214 112 doc3 1
215 113 doc4 1
216 113 doc5 2
217 113 doc6 3
218 113 doc7 4

notice_details - 这个表有发送通知文件的记录。 is_archived = 0 表示它是事件的并且只考虑那些记录。

id   customer_id   notice_id   notice_document_id   is_archived
1 3133 111 211 0
2 3133 111 212 0
3 3134 112 214 0
4 3135 113 216 0

customers - 每个客户都有一个 notice_id 用于发送文档。

id   customer_name notice_id
3133 abc 111
3134 xyz 112
3135 pqr 113

所有列都定义为 NOT NULL,并且参照完整性通过 FK 约束强制执行。

我需要为客户获取连续或下一个文档:

  1. 如果我发送了前两个文档(如 order_num = 12),那么下一个文档将是第三个(order_num = 3 >) - 例如示例中的客户 3133。
  2. 如果我直接发送了第二份文件(例如 order_num = 2,那么下一份文件也将是第三份文件 - 例如客户 3135。
  3. 如果最后一份文件已经发送,则不要发送任何文件。
  4. 如果尚未发送文件,则发送第一个文件。

我尝试使用 group by notice_id, customer_id 获取 notice_details 表中最后插入的行并获取发送的 order_num 但那赢了涵盖所有场景。
我还尝试跳过那些已经发送但也不涵盖该场景的行。

我该如何管理?

最佳答案

假设 notice_documents.idorder_num 单调递增(这使得列 order_num 冗余噪声),这应该满足所有要求:

SELECT DISTINCT ON (c.id, ndo.notice_id)
c.id AS customer_id, notice_id, ndo.id AS notice_document_id
FROM customers c
JOIN notice_documents ndo USING (notice_id)
WHERE NOT EXISTS (
SELECT 1
FROM notice_details
WHERE customer_id = c.id
AND notice_id = c.notice_id
AND is_archived -- "consider those records only"
AND notice_document_id >= ndo.id
)
ORDER BY c.id, notice_id, ndo.id;

它返回比已为每个客户和通知组合发送的最高文档 ID 更高的 notice_document_id 的文档。 (没有任何文件已经发送。)

如果您有并发访问,则需要采取更多措施来避免竞争条件。相关:

关于 DISTINCT ON:

如何排除已经从另一个表中引用的行:

对于单个给定的customer_id(解决问题更新)更简单:

SELECT DISTINCT ON (notice_id)
notice_id, ndo.id AS notice_document_id
FROM customers c
JOIN notice_documents ndo USING (notice_id)
WHERE c.customer_id = $customer_id -- input customer here
WHERE NOT EXISTS (
SELECT 1
FROM notice_details
WHERE customer_id = c.id
AND notice_id = c.notice_id
AND is_archived -- "consider those records only"
AND notice_document_id >= ndo.id
)
ORDER BY notice_id, ndo.id;

关于sql - 按 order_num 字段查找下一个连续行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43954777/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com