首页 > 解决方案 > SQL - 如何查找两行之间缺少值的条目

问题描述

我们在我的工作中使用 Presto SQL。我花了几个小时试图寻找这个问题的答案,但找不到答案,而且很难搜索。解决这个问题为解决许多问题打开了大门。

我需要编写一个查询,尝试查找存在 REQUEST_CANCEL & CHARGED 但缺少 CANCEL_ACCOUNT 的所有条目。

CHARGED 和 CANCEL_ACCOUNT 应始终在 REQUEST_CANCEL 之后。

表名:CUSTOMER_INFO

|DATE_TIME|CUST_ID |ACTION        |
|20180726 |1234    |CHARGED       |
|20180726 |1234    |CANCEL_ACCOUNT|
|20180726 |1234    |REQUEST_CANCEL|

所有这些值都存在于同一个表中。这是我到目前为止所拥有的。

SELECT *
FROM
    (SELECT *
    FROM CUSTOMER_INFO
        WHERE 
        DATE_TIME = 20180726
        AND ACTION = REQUEST_CANCEL) as a
JOIN
    (SELECT *
    FROM CUSTOMER_INFO
    WHERE
    DATE_TIME = 20180726
    AND ACTION = CHARGED) as b
ON a.CUST_ID = b.CUST_ID
WHERE 
    a.TIME < b.TIME

让我以一种有意义的方式解释它。

A = REQUEST_CANCEL
B = CANCEL_ACCOUNT
C = CHARGED

如何查询 A 和 C 何时存在但 B 缺失。顺序必须是精确的 A > B > C。它本质上是在查询两个确实存在的值之间不存在的东西。在我当前的查询中,B 可以在两个值之间返回,这不是我想要的。

标签: sqlpresto

解决方案


使用group byhaving

select cust_id
from customer_info ci
where date_time = 20180726 and
      action in ('REQUEST_CANCEL', 'CHARGED', 'CANCEL_ACCOUNT')
group by cust_id
having sum(case when action = 'REQUEST_CANCEL' then 1 else 0 end) > 0 and
       sum(case when action = 'CHARGED' then 1 else 0 end) > 0 and
       sum(case when action = 'CANCEL_ACCOUNT' then 1 else 0 end) = 0 ;

每个都sum()计算具有该操作的客户的匹配记录数。> 0说存在一个。= 0说不存在。

数据库对于这个逻辑无关紧要。 是一个使用 MySQL 的 SQL Fiddle。


推荐阅读