SQL - 如何 "filter out" 拥有超过 1 个状态的人

SQL - How to "filter out" people who has more than 1 status

我试图在这里找到这个问题,但我可能不知道要搜索的确切术语。

这是问题所在:

我有这组客户(见图)。我只需要过滤状态为 "user_paused" 或 "interval_paused" 的那些。同一个customer_id可能有不止1个状态,有时,这个状态可以是"active"。如果是这样,这个客户应该不会出现在我的最终结果中。

见客户 809 - 他不应出现在我的最终结果中,因为他的状态为 "active"。其他都很好,因为他们只有暂停状态。

我仍然不知道如何从这里开始。

非常感谢。

select * from table
where customer_id in 
(select customer_id from table 
where status in ('interval_paused','user_paused') )
SELECT DISTINCT  customer_id FROM TABLE
WHERE status IN ( 'user_paused','interval_paused')
EXCEPT
SELECT DISTINCT  customer_id FROM TABLE
WHERE status = 'active'

一种方法使用 group byhaving:

select customer_id
from t
group by customer_id
having sum(case when status not in ('user_paused', 'interval_paused') then 1 else 0 end) = 0;

要排除任一列中具有 'active' 的任何客户,请使用以下内容:

select * from customers 
where paused_statuses != 'active'
and status != 'active';

您可以很容易地找到状态为 'active' 的所有客户:

SELECT customerid FROM table WHERE status = 'active'

如果您想从结果中排除任何客户(如果他们有一个活动行),您可以在子查询中执行此操作:

SELECT * FROM table WHERE /* your other query restrictions */
AND customerID NOT IN
(
    SELECT customerid FROM table WHERE status = 'active'
)

这样您就可以删除具有任何 'active' 行的 customerid 的任何行。

请注意,子查询并不总是最有效的解决方案 - 在某些情况下,子查询会使您的查询非常缓慢。

不确定您是否需要 distinct,但这里有 2 种方法。我认为两者都可以在 Impala 中使用,但以防万一您有选择。第一个使用 "left excluding join"(进行连接然后排除匹配的行),这使我们能够忽略活动状态的客户。第二种使用更传统的 "not exists" 方法来删​​除具有活动状态的 customer_ids。

select /* distinct */ t1.customer_id 
from table t1
left join table t2 on  t1.customer_id = t2.customer_id and t2.status = 'active'
where t2.customer_id IS NULL
and t1.status in ('interval_paused','user_paused')
;

select /* distinct */ t1.customer_id 
from table t1
where t1.status in ('interval_paused','user_paused')
and NOT EXISTS (
     select null
     from table t2
     where t1.customer_id = t2.customer_id
     and t2.status = 'active'
     )
;

如果您现有的查询很复杂,那么要简化这些添加,请使用这样的 WITH clause

WITH MyCTE AS (

    -- place the whole existing query here

)
select /* distinct */ t1.customer_id 
from MyCTE t1
left join MyCTE t2 on  t1.customer_id = t2.customer_id and t2.status = 'active'
where t2.customer_id IS NULL
and t1.status in ('interval_paused','user_paused')
;

请注意,您为其指定的名称 ("MyCTE") 可以在后续查询中重复使用 - 这确实是一个非常有用的功能。

如果您想知道为什么我使用 "MyCTE" 作为名称,通常 WITH 创建的结构称为 common table expressions (CTE)。

 SELECT customer_id, paused_statuses, status
 FROM Customer
 WHERE NOT IN (SELECT customer_id, paused_statuses, status
               FROM Customer
               WHERE status = user_paused 
                  AND status = active 
                  AND status = interval_paused) 
  GROUP BY customer_id

  OR

 SELECT customer_id, paused_statuses, status
 FROM Customer
 WHERE status = user_paused 
     AND status = interval_paused
     AND status <> active
 GROUP BY customer_id