首页 > 解决方案 > 我如何过滤一对多的所有结果

问题描述

想象以下表格:

CREATE TABLE item (code string);
CREATE TABLE item_event (id int, item_code string, event int, date smalldatetime);

item:
code
item1
item2
item3
item4

item_event:
id | item_code  | event | date
1  |  item1     | 123   | 2021-05-04 05:50
2  |  item1     | 456   | 2021-05-04 06:50
3  |  item2     | 123   | 2021-05-04 05:50
4  |  item2     | 678   | 2021-05-04 08:50
5  |  item3     | 456   | 2021-05-04 05:50
6  |  item3     | 890   | 2021-05-04 09:50
7  |  item4     | 123   | 2021-05-04 11:50
8  |  item4     | 456   | 2021-05-04 20:50
9  |  item4     | 890   | 2021-05-04 01:50

如何选择没有 456 事件的项目或日期在 890 事件之后的 456 事件(如果有)?

所以在这种情况下它会返回item2and item4

无法弄清楚如何在 SQL 中执行此操作。我尝试过的一切都只是过滤掉单个事件,而不是查看“按 item_code 分组”的集合。

标签: sqlsql-serverone-to-many

解决方案


使用聚合我们可以尝试:

WITH cte AS (
    SELECT item_code
    FROM item_event
    GROUP BY item_code
    HAVING COUNT(CASE WHEN event = 456 THEN 1 END) = 0 OR
           MIN(CASE WHEN event = 890 THEN date END) <
           MIN(CASE WHEN event = 456 THEN date END)
)

SELECT *
FROM item_event
WHERE item_code IN (SELECT item_code FROM cte);

演示

上述HAVING条款的逻辑是保留根本没有456 事件的任何记录集,或者item_code保留最早的 890 事件发生最早的 456 事件之前的任何记录。在这种情况下,这意味着每个 456 事件至少有一个更早的 890 事件。item_code


推荐阅读