您可以将查询一分为二,然后将它们联合起来:
SELECT idx1, NULL AS idx2
FROM myTable
WHERE idx1 IN (1,2,3)
UNION ALL
SELECT NULL, idx2
FROM myTable
WHERE idx2 IN (4,5,6);
编辑:我知道您说过您知道可以使用 UNION 来完成,但您担心要明确在每个条件下找到了哪些行。
上面的解决方案应该满足您将“其他”列显示为 NULL 的要求,因为我们可以将 NULL 显式放入选择列表中,而不是命名其他列。
您应该在 UNION 的第一个查询中定义列别名。 UNION 中后续查询的列名将使用第一个查询中定义的列别名。
来自@Kaii 的回复:
索引合并优化并不像您预期的那样经常提供帮助。这是一个演示,在 MySQL 8.0.14 上测试:
CREATE TABLE `mytable` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`idx1` int(11) DEFAULT NULL,
`idx2` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
KEY `idx1` (`idx1`),
KEY `idx2` (`idx2`)
);
我用 1M+ 行填充它,idx1 和 idx2 的随机值介于 0 和 50 之间。
select count(*) from mytable;
+----------+
| count(*) |
+----------+
| 1048576 |
+----------+
使用OR 的查询不执行索引合并,而是执行表扫描 (type=ALL):
explain SELECT idx1, idx2 FROM myTable WHERE idx1 IN(1,2,3) OR idx2 IN(4,5,6);
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| 1 | SIMPLE | myTable | NULL | ALL | idx1,idx2 | NULL | NULL | NULL | 1046577 | 51.00 | Using where |
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
而我的UNION 解决方案确实使用了两个索引,并且不使用临时表:
explain SELECT idx1, NULL AS idx2 FROM myTable WHERE idx1 IN (1,2,3) UNION ALL SELECT NULL, idx2 FROM myTable WHERE idx2 IN (4,5,6);
+----+-------------+---------+------------+-------+---------------+------+---------+------+--------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+------+---------+------+--------+----------+--------------------------+
| 1 | PRIMARY | myTable | NULL | range | idx1 | idx1 | 5 | NULL | 113264 | 100.00 | Using where; Using index |
| 2 | UNION | myTable | NULL | range | idx2 | idx2 | 5 | NULL | 112678 | 100.00 | Using where; Using index |
+----+-------------+---------+------------+-------+---------------+------+---------+------+--------+----------+--------------------------+
我分析了这两个查询,发现UNION 查询在这种情况下要快很多。
show profiles;
+----------+------------+-----------------------------------------------------------------------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-----------------------------------------------------------------------------------------------------------------------------+
| 1 | 0.22477500 | SELECT idx1, idx2 FROM myTable WHERE idx1 IN(1,2,3) OR idx2 IN(4,5,6) |
| 2 | 0.05573200 | SELECT idx1, NULL AS idx2 FROM myTable WHERE idx1 IN (1,2,3) UNION ALL SELECT NULL, idx2 FROM myTable WHERE idx2 IN (4,5,6) |
+----------+------------+-----------------------------------------------------------------------------------------------------------------------------+