簡體   English   中英

MySQL,將多個查詢合而為一

[英]MySQL, combine several queries in one

我有這樣的桌子

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

我有以下三個查詢:

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 所提到的,表中缺少索引:

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

我的版本如下所示:

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`);

添加雙字段索引后,“使用位置”更改為“使用位置; 使用索引

我無法想象您可以比單獨查詢每個索引更有效。 在我腦海中浮現的場景中,我會沿用以下方式:

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

where field_3 != 2 and field_2 != 2情況下,極不可能使用您的索引之一。 對於大量記錄, field_3 != 2應該為true。 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;

您可以使用MYSQL Union All命令 我已經創建了一個模擬表並插入了測試數據。

+---------+---------+---------+
| 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查詢是

SELECT COUNT()作為field_1_is_2從MY_TABLE其中field_1 = 2 UNION ALL SELECT COUNT()作為field_2_is_4從MY_TABLE其中field_2 = 4 UNION ALL SELECT COUNT(*)作為field_3_is_5從MY_TABLE其中field_3 = 5;

這給像這樣的結果

+--------------+
| field_1_is_2 |
+--------------+
|            1 |
|            4 |
|            1 |
+--------------+

您應該能夠將結果作為第一行,第二行和第三行。 這也將利用索引的力量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM