sql - 考虑到应出现在组行中的数据,如何确定表中是否存在一组数据?

标签 sql sql-server grouping set-operations

我正在将数据写入表中,并为每批写入的数据分配一个“group-id”。为了说明这一点,请考虑下表。

GroupId  Value
-------  -----
      1      a
      1      b
      1      c
      2      a
      2      b
      3      a
      3      b
      3      c
      3      d

在此示例中,存在三组数据,每组数据具有相似但不同的值。

如何查询此表以查找包含给定值集的组?例如,如果我查询 (a,b,c),结果应为组 1。类似地,查询 (b,a) 应结果为组 2,查询 (a,b,c,e) 应结果为组 1。应该导致空集。

我可以编写一个执行以下步骤的存储过程:

  • 从群组中选择不同的 GroupId - 并存储在本地
  • 对于每个不同的 GroupId:在输入值和表值(对于组)之间执行设置差异(异常(exception)),反之亦然
  • 如果两个集合差值运算都生成空集,则返回 GroupId

这似乎有点过分,我希望利用 SQL 中的其他一些命令来简化。是否有更简单的方法可以在此上下文中执行集合比较,或者选择包含查询的确切输入值的组 ID?

最佳答案

这是一个集合内的查询。我喜欢使用group byhaving来解决它:

select groupid
from GroupValues gv
group by groupid
having sum(case when value = 'a' then 1 else 0 end) > 0 and
       sum(case when value = 'b' then 1 else 0 end) > 0 and
       sum(case when value = 'c' then 1 else 0 end) > 0 and
       sum(case when value not in ('a', 'b', 'c') then 1 else - end) = 0;

having 子句中的前三个条件检查每个元素是否存在。最后一个条件检查是否没有其他值。这种方法非常灵活,适用于您要查找的值的各种排除和包含条件。

编辑:

如果你想传入一个列表,可以使用:

with thelist as (
      select 'a' as value union all
      select 'b' union all
      select 'c'
     )
select groupid
from GroupValues gv left outer join
     thelist
     on gv.value = thelist.value
group by groupid
having count(distinct gv.value) = (select count(*) from thelist) and
       count(distinct (case when gv.value = thelist.value then gv.value end)) = count(distinct gv.value);

此处的 having 子句计算匹配值的数量,并确保其与列表的大小相同。

编辑: 由于缺少表别名,查询编译失败。使用正确的表别名更新。

关于sql - 考虑到应出现在组行中的数据,如何确定表中是否存在一组数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22104670/

相关文章:

mysql - INSERT 语句 SELECT CONCAT

c# - 如何使用 C# 从 SqlConnection 返回多个结果

c# - EF Core 是否可以在针对具有转换的属性的查询中调用方法?

c# - 使用 LINQ 处理大型 SQL 查询

mysql - 如何在 MySQL 中按日期对相关结果进行分组和排序

sql - C 语言的 DB2 包

c# - SqlConnection 命令在删除时不会引发异常

c# - 如何在 C# 中违反约束的异常中获取列名称

json - 使用 jq 解析每行 JSON 记录?

r - 在数据框中查找唯一的行组