mysql SQL group by -匹配给定列表中的所有项

wz8daaqr  于 2023-06-04  发布在  Mysql
关注(0)|答案(4)|浏览(357)

我有一个表格,像下面这样:
| id|设备id|器件模型|
| - -----|- -----|- -----|
| 1|一百零一|一个|
| 1|二百零一|B|
| 1|二百零二|B|
| 2|一百零二|一个|
| 2|三百零一|C类|
| 3|一百零三|一个|
| 3|二百零三|B|
| 3|三百零二|C类|
我想选择一组ID与特定的设备型号在列表中给出。起初,我试着:

SELECT id
FROM tbl
WHERE device_model IN ('A', 'B')
GROUP BY id

但这就像OR一样...如果ID只有('A', 'B')中的一个,则返回该ID。这不是我想要的行为,相反,我想要的是AND行为。
我想我可以用这个:

SELECT id
FROM tbl
WHERE device_model IN ('A', 'B')
HAVING COUNT(DISTINCT device_model) = 2;

但是,这返回id 1和3;但我只要一个不是三个因为它也有设备型号C。
我该怎么做才能获得包含精确列表中给出的设备型号的id?

dy1byipe

dy1byipe1#

可以将HAVING子句与条件聚合沿着使用。

SELECT id
FROM tbl
GROUP BY id
HAVING COUNT(DISTINCT CASE WHEN device_model IN ('A', 'B') THEN device_model END) = 2
   AND COUNT(DISTINCT CASE WHEN device_model NOT IN ('A', 'B') THEN device_model END) = 0;

在这个查询中,我们使用条件聚合来计算与指定模型匹配和不匹配的不同device_models。CASE语句用于根据IN和NOT IN条件有条件地计算值。
HAVING子句然后检查匹配的device_models的计数是否等于指定模型的数量(在本例中为2),并且不匹配的device_models的计数是否为0。这可确保仅选择具有所有指定模型的id组,而不选择其他任何id组。

s4n0splo

s4n0splo2#

HAVING子句中添加GROUP BY子句和另一个条件,用于检查现场device_model中是否仅存在A、B。

SELECT id
FROM tbl
GROUP BY id
HAVING COUNT(DISTINCT device_model) = 2
   AND MIN(device_model IN ('A', 'B')) = 1;

这应该可以在MySQL上工作,并且应该可以很好地推广到您想要检查的任何n个元素。只需将所有元素添加到数组中,并更新不同元素的数量即可。

输出

| id|
| - -----|
| 1|
查看演示here

tjvv9vkg

tjvv9vkg3#

一个完全不同的方法:

select id from tbl where device_model = 'A'
intersect
select id from tbl where device_model = 'B'
except
select id from tbl where device_model not in ('A', 'B');

我做了一些基本的性能测试,这个查询实际上比我尝试的所有GROUP BY/HAVING查询快好几倍。(但不能在MySQL上运行。
我最好的GROUP BY/HAVING查询是:

SELECT id
FROM tbl
GROUP BY id
HAVING COUNT(case when device_model not in ('A', 'B') then 1 end) = 0
   AND MIN(device_model) <> MAX(device_model);
kd3sttzy

kd3sttzy4#

因为你想测试“关系除法余数”,你必须去掉where子句,并在having子句中添加一个额外的条件:

SELECT id
FROM tbl
GROUP BY id
HAVING COUNT(DISTINCT device_model) = 2
AND    COUNT(DISTINCT CASE WHEN device_model IN ('A', 'B') THEN device_model END) = 2

相关问题