如何通过过滤mysql中包含值的多个列来获取行?

q35jwt9p  于 2021-06-18  发布在  Mysql
关注(0)|答案(2)|浏览(292)

我有一个mysql表,名为 fruits :

我想从列所在的表中选择行 fruit1 , fruit2 ,和 fruit3 仅包含集合中的值 [apple, pear, melon]
只有 apple 只有 pear 只有 melon 只有两者都有 apple 以及 pear 只有两者都有 apple 以及 melon 只有两者都有 pear 以及 melon 只有 apple , pear 以及 melon 对于我的示例数据,行将 1, 5, 8 .
我尝试了以下查询:

SELECT * FROM fruits WHERE 'apple' in (fruit1, fruit2, fruit3)

给了我所有包含 apple 在一个 fruit 柱。但是,我不知道如何过滤多个列。

tzxcd3kk

tzxcd3kk1#

我的假设是 fruit 表中的值是 NULL . 在这种情况下,此查询将为您提供所需的结果:

SELECT *
FROM fruits
WHERE (fruit1 IN ('apple', 'melon', 'pear') OR fruit1 IS NULL)
  AND (fruit2 IN ('apple', 'melon', 'pear') OR fruit2 IS NULL)
  AND (fruit3 IN ('apple', 'melon', 'pear') OR fruit3 IS NULL)

输出

id  fruit1  fruit2  fruit3
1   apple       
5   melon           pear
8   apple           melon

如果空白值只是空字符串,则将查询更改为

SELECT *
FROM fruits
WHERE (fruit1 IN ('apple', 'melon', 'pear') OR fruit1 = '')
  AND (fruit2 IN ('apple', 'melon', 'pear') OR fruit2 = '')
  AND (fruit3 IN ('apple', 'melon', 'pear') OR fruit3 = '')

在dbfiddle上演示

iszxjhcz

iszxjhcz2#

理想解决方案:
您可以通过创建两个表来规范化它。第一张table是 id 以及 area .

Create Table area_master (area_id int auto_increment, 
                          area varchar(32), 
                          description varchar(32)
                          Primary Key(area_id));
Insert into area 
       (area, description) 
Values ('areaA', 'Hi'), 
       ('areaB', 'Hello'); -- add more rows as you need

第二张table是 area_id (fk从 area_master 表), attribute , value , attribute_order :

Create Table area_fruits (id int auto_increment, 
                          area_id int, 
                          attribute varchar(32), 
                          value varchar(32), 
                          attribute_order int
                          Primary Key(id));

Insert into area_fruits 
       (area_id, attribute, value, attribute_order) 
Values (1, 'fruit', 'apple', 1),
       (2, 'fruit', 'banana', 1),
       (2, 'fruit', 'apple', 3); -- add more rows as needed

现在,获取数据的查询将如下所示,您不需要每次都更改它,因为您添加了新的结果:-)

SELECT am.id, am.area, am.description 
FROM area_master AS am 
JOIN area_fruits AS af ON af.area_id = am.area_id AND 
                          af.attribute = 'fruit' 
GROUP BY am.id, am.area, am.description 
HAVING SUM(af.value IN ('apple', 'pear', 'melon')) = COUNT(*)

p、 s:可能会有更多的改进,比如添加外键约束等,但我希望您能理解要点。
原始问题:
使用 Where 我们只考虑那些至少有一个果列的行 apple , pear ,或 melon 现在,我们做一个 Group Byid ,并使用 Having 忽略果列不是空的行,它们的值不是空的 apple , pear ,和 melon .
请尝试以下操作:

SELECT id 
FROM fruits 
WHERE fruit1 IN ('apple', 'pear', 'melon') OR 
      fruit2 IN ('apple', 'pear', 'melon') OR 
      fruit3 IN ('apple', 'pear', 'melon')
GROUP BY id 
HAVING SUM(fruit1 NOT IN ('apple', 'pear', 'melon') AND fruit1 <> '') = 0 AND 
       SUM(fruit2 NOT IN ('apple', 'pear', 'melon') AND fruit2 <> '') = 0 AND 
       SUM(fruit3 NOT IN ('apple', 'pear', 'melon') AND fruit3 <> '') = 0

p、 这是个糟糕的设计。每当有n个类似的列时,就应该考虑对其进行规范化。

相关问题