[英]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.