使用 Group By 作为 where 子句的一部分
Posted
技术标签:
【中文标题】使用 Group By 作为 where 子句的一部分【英文标题】:Using Group By as part of a where clause 【发布时间】:2019-11-11 14:46:23 【问题描述】:我正在尝试使用 SQL Server 从数据集中删除某些记录。我的帖子标题可能不准确,因为可能存在比我想象的更好的解决方案。
在我的查询中,我从表 A 中进行选择,我希望最终得到的行应满足以下条件:
-
A.ItemNumber = B.ItemNumber 的所有行
A.ItemNumber B.ItemNumber AND 该行的 Task 值没有其他行符合条件 #1 的所有行。
所以对于下面的例子:
为我们提供 ItemNumber 102、104、106 行。
为我们提供 ItemNumber 105 行。 100、101 已从数据集中删除,因为它们的任务 (1) 与表 B 的 ItemNumber 102 关联。103 与任务 (2) 关联的 ItemNumber 104 相同。
Table A
Task ItemNumber
1 100
1 101
1 102
2 103
2 104
3 105
4 106
Table B
ItemNumber Data
102 aaa
104 bbb
106 ccc
我最初的想法是将表 A 加载到临时表中,与表 B 进行 LEFT JOIN,并从 temp table 中删除(数据为空并且在此处插入某种分组逻辑)。但是我完全无法弄清楚可以解决该问题的分组逻辑。我度过了一个周末,希望能找到解决方案,但现在我放弃并寻求建议。
【问题讨论】:
同时指定预期结果。 想要的结果实际上是从表 A 中删除不符合所列条件的行。 ItemNumber 100、101 和 103 本质上是假货。 【参考方案1】:使用满足第一个条件的 CTE 和 UNION ALL 返回其余行:
with cte as (
select a.*
from TableA a
where exists (select 1 from TableB where ItemNumber = a.ItemNumber)
)
select * from cte
union all
select a.* from TableA a
where not exists (select 1 from cte where Task = a.Task)
order by Task
请参阅demo。 结果:
Task ItemNumber
1 102
2 104
3 105
4 106
【讨论】:
【参考方案2】:一种表达方式将所有过滤逻辑放在where
子句中:
select a.*
from tablea a
where exists (select 1
from tableb b
where b.itemnumber = a.itemnumber
) or
not exists (select 1
from tableb b2 join
tablea a2
on b2.itemnumber = a2.itemnumber
where a2.task = a.task
);
【讨论】:
【参考方案3】:SELECT *
FROM TABLEA AS A
LEFT JOIN TABLEB AS B ON A.ItemNumber = B.ItemNumber
WHERE B.ItemNumber IS NOT NULL -- critera 1
OR (B.ItemNumber IS NULL AND B.ItemNumber NOT IN
(SELECT A.ItemNumber
FROM TABLEA AS A
JOIN TABLEB AS B ON A.ItemNumber = B.ItemNumber)) -- criteria 2
【讨论】:
我读错了,还是 NOT IN 子查询会返回 102、104、106?然后哪个会基本上返回我们完整的 LEFT JOIN(至少在示例表中的数据集)? @boc4life -- 取决于数据。以上是关于使用 Group By 作为 where 子句的一部分的主要内容,如果未能解决你的问题,请参考以下文章
在连接中使用 Where 子句,以及 Group by 和 Order By
不能在 Group by/Order by/Where/ON 子句中使用 Group 或 Aggregate 函数(min()、max()、sum()、count()、...等)