MySQL - 选择一些值为null的行

时间:2015-02-25 11:14:41

标签: mysql

我的价值是' foo',' bar'和' buz'。我想从下表中选择第1行和第3行:

+----+------+------+------+
| Id | Col1 | Col2 | Col3 |
+----+------+------+------+
|  1 | foo  |      |      |
|  2 | foo  | bar  | buz  |
|  3 |      | bar  | buz  |
+----+------+------+------+

考虑以下因素,最佳MySQL查询是什么:

  • 空格为空
  • 我有n列,其中4< n< 20
  • 会有几百行
  • 我将在一行中选择特定的列组合,其中只能设置提供的值,其余值必须为null。例如:我需要这样的查询

SELECT * FROM my_table WHERE Col1 = foo OR (Col2 = bar AND Col3 = buz);

只返回第1行和第3行。

换句话说,我希望有一个查询只返回具有某些值组合的行,而不是coln = 'some_val'的行和我们不会返回的行。关心他人。

原因是我希望在1个查询中有5个组合,并且我希望避免在任何地方写(...) coln <> NULL(...)

我很感激你的建议。

2 个答案:

答案 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,它可以使用整个索引