繁体   English   中英

mysql select 结果基于 2 列或更多列的多个匹配条件

[英]mysql select result based on multiple matching criteria of 2 or more columns

我的桌子是这样的:

CREATE TABLE candidate_tbl  (
  `name` VARCHAR(1),
  `degree` VARCHAR(41),
  `doneMasters` VARCHAR(6)
);

INSERT INTO candidate_tbl 
  (`name`, `degree`, `doneMasters`)
VALUES
  ('A', 'MBA', 'true'),
  ('A', 'MS', 'false'),
  ('B', 'MBA', 'true'),
  ('B', 'MS', 'true'),
  ('C', 'MBA', 'false'),
  ('C', 'MS', 'false'),
  ('D', 'MBA', 'false'),
  ('D', 'MS','true'),
  ('E', 'MBA', 'false'),
  ('E', 'MS', 'false'),
  ('F', 'MBA', 'false'),
  ('F', 'MS', 'true'),
  ('G', 'MBA', 'false'),
  ('G', 'MS', 'false'),
  ('H', 'MS', 'true'),
  ('H', 'MS', 'true');

我想要既没有 MS 也没有 MBA 的候选人名单,即 C,E 和 G

我尝试了这 4 种方法, 这里给出了小提琴

方法一

SELECT name,count(*) FROM candidate_tbl
WHERE doneMasters = 'false'
AND doneMasters = 'false'
GROUP BY name
HAVING count(*) = 2;

方法二

SELECT DISTINCT name FROM candidate_tbl ct1 WHERE NOT EXISTS
(
SELECT name FROM candidate_tbl ct2 WHERE ct1.name = ct2.name and doneMasters = 'true'
);

方法三

SELECT name FROM (SELECT name,group_concat(doneMasters) as dmf FROM candidate_tbl
GROUP BY name) dd
WHERE dmf = 'false,false';

方法四

SELECT name FROM (SELECT name, group_concat(doneMasters) as dmf FROM candidate_tbl
GROUP BY name) dd
WHERE dmf = 'false,false';

我想知道在性能和准确性方面哪个是最佳解决方案,或者其他替代解决方案。

你的数据模型对我来说没有意义。 例如,为什么要在表中存储负面信息?

最好的方法是对数据模型进行规范化,以拥有单独的候选人及其学位表。 然后使用not exists

select c.*
from candidates c
where not exists (select 1
                  from candidate_degrees cd
                  where cd.candidate_id = c.candidate_id and
                        cd.degree in ('MS', 'MBA')
                 );

这对您的数据模型来说是一个相当大的变化:

  • 学位表将只包含存在的学位(可能还有其他信息,例如年份、学校等)。
  • 候选人将通过可用于加入的 ID 进行标识。

尝试这个。

SELECT name FROM candidate_tbl 
WHERE doneMasters = 'false' 
AND degree in ('MBA', 'MS') 
GROUP BY name HAVING count(1) = 2;

演示在这里: DB-FIDDLE

解决办法很简单

SELECT name FROM candidate_tbl 
WHERE degree in ('MBA', 'MS') AND doneMasters = 'false' 
GROUP BY name;

它将从没有完成 MBA 或 MS 的列表中返回一个唯一的名字。

如果对于每个name ,在degree列中总是恰好有 2 行值为'MBA''MS' ,则没有理由检查或过滤列degree
最简单的方法是按名称分组,过滤doneMasters列中为true的行,并检查HAVING子句是否在结果中有 2 行(这 2 行将在doneMasters列中包含'false' ):

SELECT name
FROM candidate_tbl
WHERE doneMasters = 'false'
GROUP BY name
HAVING COUNT(*) = 2

请参阅演示
结果:

> | name |
> | :--- |
> | C    |
> | E    |
> | G    |

请注意,像doneMasters这样的标志列会更好(为了清晰、编码简单、更少的存储空间和更好的性能)定义为BOOLEAN 请参阅演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM