MySQL,将多个查询合二为一

时间:2016-10-27 17:44:13

标签: mysql sql

我有一张这样的表

field_1  field_2  field_3
-------  -------  -------
      3        1        5
      2        1        1
      1        2        1
      1        4        1

我有这3个问题:

select count(*) as field_1_is_2 from my_table where field_1 = 2;
select count(*) as field_2_is_4 from my_table where field_2 = 4;
select count(*) as field_3_is_5 from my_table where field_3 = 5;
select count(*) as fields_combined from my_table where field_3 != 2 and field_2 != 2;

如何在一个查询中组合上述查询?

一个选项可能是:

select
  sum(if(field_1 = 2, 1, 0)) as field_1_is_2,
  sum(if(field_2 = 4, 1, 0)) as field_2_is_5,
  sum(if(field_3 = 5, 1, 0)) as field_3_is_5,
  sum(if(field_3 != 2 and field_2 != 2, 1, 0)) as fields_combined
from my_table;

但表格非常大,我想使用正确的索引,这种方法没有使用它们。

这是表格描述:

CREATE TABLE `my_table` (
  `field_1` int(11) DEFAULT NULL,
  `field_2` int(11) DEFAULT NULL,
  `field_3` int(11) DEFAULT NULL,
  KEY `index_field_1` (`field_1`),
  KEY `index_field_2` (`field_2`),
  KEY `index_field_3` (`field_3`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

所以,问题是,如何在一个查询中组合(如果可能)上述查询并正确使用索引?

更新

作为@ ralf.w is mentioning,表格中缺少一个索引:

ALTER TABLE `my_table` ADD KEY `index_field_2_and_3` (`field_2`,`field_3`);

4 个答案:

答案 0 :(得分:1)

我的版本看起来像这样:

select
(select count(*) as field_1_is_2 from my_table where field_1 = 2) as field_1_is_2,
(select count(*) as field_2_is_4 from my_table where field_2 = 4) as field_2_is_4,
(select count(*) as field_3_is_5 from my_table where field_3 = 5) as field_3_is_5,
(select count(*) as fields_combined from my_table 
where field_3 != 2 and field_2 != 2) as fields_combined;

让优化器对其余部分进行优化和组合。

由EXPLAIN预先执行,我们看到了这一点:

1,PRIMARY ,,,,,,,,,没有使用的表
5,SUBQUERY,my_table,ALL,index_field_2,index_field_3 ,,, 4,使用位置
4,SUBQUERY,my_table,ref,index_field_3,index_field_3,5,const,1,使用索引
3,SUBQUERY,my_table,ref,index_field_2,index_field_2,5,const,1,使用索引
2,SUBQUERY,my_table,ref,index_field_1,index_field_1,5,const,1,使用索引

这里真的缺少的是field_3和field_2的索引:

ALTER TABLE `my_table` ADD KEY `index_field_2_and_3` (`field_2`,`field_3`);

将双字段索引“使用位置”更改为“使用位置; 使用索引

答案 1 :(得分:1)

我无法想象你能比单独查询每个索引更有效地做到这一点。在突然出现在我脑海中的场景中,我会使用以下几点:

select "field_1_is_2" as criteria, count(*) from my_table where field_1 = 2
union all
select "field_2_is_4" as criteria, count(*) from my_table where field_2 = 4
union all
select "field_3_is_5" as criteria, count(*) from my_table where field_3 = 5
union all
select "fields_combined" as criteria, count(*) from my_table where field_3 != 2 and field_2 != 2;

在单独的行中返回每个值:

criteria    count(*)
field_1_is_2    1
field_2_is_4    1
field_3_is_5    1
fields_combined 3

答案 2 :(得分:1)

使用where field_3 != 2 and field_2 != 2,您的某个索引将被使用的可能性非常小。对于大量的记录,field_3 != 2应该是真的。 field_2 != 2也是如此。 DBMS不扫描索引,例如,80%的记录使用一个标准,另一个70%使用另一个标准,然后与集合相交。它宁愿简单地从头到尾读取一次表,即执行全表扫描。

因为它将读取整个表的计数,所以不应该在单独的查询中获得其他计数,而是在运行中获取计数。所以带条件和的选项是要走的路。在标准SQL中:

select
  count(case when field_1 = 2 then 1 end) as field_1_is_2,
  count(case when field_2 = 4 then 1 end) as field_2_is_4,
  count(case when field_3 = 5 then 1 end) as field_3_is_5,
  count(case when field_3 != 2 and field_2 != 2 then 1 end) as fields_combined
from my_table;

在MySQL中:

select
  sum(field_1 = 2) as field_1_is_2,
  sum(field_2 = 4) as field_2_is_4,
  sum(field_3 = 5) as field_3_is_5,
  sum(field_3 != 2 and field_2 != 2) as fields_combined
from my_table;

答案 3 :(得分:-1)

您可以使用MYSQL Union All command。我创建了一个simillar表并插入了测试数据。

+---------+---------+---------+
| field_1 | field_2 | field_3 |
+---------+---------+---------+
|       3 |       1 |       5 |
|       2 |       1 |       1 |
|       1 |       2 |       1 |
|       1 |       4 |       1 |
|       1 |       4 |       2 |
|       1 |       4 |       3 |
|       1 |       4 |       4 |
+---------+---------+---------+

现在我正在使用的sql查询是

  

从my_table中选择count()作为field_1_is_2,其中field_1 = 2 union   所有选择计数()为my_table的field_2_is_4,其中field_2 = 4    union all 从my_table中选择count(*)作为field_3_is_5,其中field_3   = 5;

这给出了像

这样的结果
+--------------+
| field_1_is_2 |
+--------------+
|            1 |
|            4 |
|            1 |
+--------------+

您应该能够将结果作为第一行,第二行和第三行。这也将利用索引的力量。