我的价值是' foo',' bar'和' buz'。我想从下表中选择第1行和第3行:
+----+------+------+------+
| Id | Col1 | Col2 | Col3 |
+----+------+------+------+
| 1 | foo | | |
| 2 | foo | bar | buz |
| 3 | | bar | buz |
+----+------+------+------+
考虑以下因素,最佳MySQL查询是什么:
SELECT * FROM my_table WHERE Col1 = foo OR (Col2 = bar AND Col3 = buz);
只返回第1行和第3行。
换句话说,我希望有一个查询只返回具有某些值组合的行,而不是coln = 'some_val'
的行和我们不会返回的行。关心他人。
原因是我希望在1个查询中有5个组合,并且我希望避免在任何地方写(...) coln <> NULL(...)
。
我很感激你的建议。
答案 0 :(得分:2)
您将使用where
子句。要找到三个值:
where 'foo' in (col1, col2, col3, . . . ) or
'bar' in (col1, col2, col3, . . . ) or
'buz' in (col1, col2, col3, . . . )
将结果限制为这三个值更加困难。您需要对每列进行比较:
where ( (col1 in ('foo', 'bar', 'buz') or col1 is null) or
(col2 in ('foo', 'bar', 'buz') or col2 is null) or
. . .
)
如果您不想全部输入代码,可以使用电子表格生成代码。
另一种选择是以下kludge:
where replace(replace(replace(concat_ws('', col1, col2, col3, . . . ),
'foo', ''
), 'bar', ''
), 'buz', ''
) = ''
将值连接在一起,然后删除您关注的值。如果删除了所有内容,则该行匹配。
注意:此问题表明您的数据结构较差。您将事物存储在应该在行中的列中。
答案 1 :(得分:1)
我希望db假设,对于查询中未提供的每个字段,要返回的整行需要为NULL。即使提供的值匹配。
在这种情况下,简单的解决方案是:
SELECT * FROM my_table WHERE
(Col1 = 'foo' AND Col2 IS NULL AND Col3 IS NULL) OR
(Col1 IS NULL AND Col2 = 'bar' AND Col3 = 'buz') OR
/* ... */
在许多情况下,这可能是一个非常好的解决方案。但是,由于MySQL's poor index use for OR
queries.,它有时可能会遇到次优的性能。特别是,如果所有列都有一个组合索引,并且想要充分利用它,那么重写查询以使用{{}会更好。 1}}(或UNION
)代替UNION ALL
:
OR
有关这两种技术的演示,请参阅this SQLFiddle,并比较执行计划(执行次对于如此小的表格而言毫无意义;您需要更多行看到任何系统的差异)。查看KEY_LEN和REF列,您可以看到,对于SELECT * FROM my_table WHERE
(Col1 = 'foo' AND Col2 IS NULL AND Col3 IS NULL) UNION ALL
SELECT * FROM my_table WHERE
(Col1 IS NULL AND Col2 = 'bar' AND Col3 = 'buz') UNION ALL
/* ... */
查询,MySQL最终仅使用OR
的索引,而使用Col1
,它可以使用整个索引