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 by
和 having
:
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
我试图在这里找到这个问题,但我可能不知道要搜索的确切术语。
这是问题所在:
我有这组客户(见图)。我只需要过滤状态为 "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 by
和 having
:
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