使用 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()、...等)

使用多个 WHERE 子句和 GROUP BY 销售人员访问 SQL、聚合总和

在 WHERE 或 GROUP BY 子句中使用列表别名

GROUP BY,WHERE,HAVING之间的区别和用法

PostgreSQL 在发送参数时在 where 中询问“group by”子句