簡體   English   中英

查詢多個子查詢效率?

[英]Query With Multiple Subqueries Efficiency?

我的數據如下所示:

State   Sex
----    ---
GA      M
GA      M
GA      F
GA      F
GA      F
NY      M
NY      M
NY      M
NY      M
NY      F
NY      F
NY      F
NY      F
NY      F

我希望結果是:

  1. 每個 state 一行
  2. col1 State
  3. col2 男性數量
  4. col3 女性數量
  5. state 的 col4 總計數
  6. col 5% 男性 by state

我正在使用的查詢是:

select t.state State, 
M.count Male, 
F.count Female, 
count(t.state) Total,
CONCAT(ROUND(CAST(M.count as float)/CAST(count(t.state) as float)*100, 2), '%') as calc
from MyTable t
join
(
  select state, count(sex) as count 
  from MyTable where sex ='M' 
  group by state) M 
  on t.state = M.state 
join (
  select state, count(sex) as count 
  from MyTable where sex ='F' 
  group by state) F 
  ON M.state = F.state
  group by t.state, m.count, F.count;

上面的查詢有效,但我想知道我是否以最有效的方式做到了這一點。 這是使用 SQLServer 完成的,但我認為這對於所有 RDBMS 應該是相同的。 鏈接在這里: http://sqlfiddle.com/#!18/7a969/87

使用條件聚合:

select t.state, 
       sum(case when sex = 'M' then 1 else 0 end) as males,
       sum(case when sex = 'F' then 1 else 0 end) as females,
       count(*) as total,
       avg(case when sex = 'M' then 1.0 else 0 end) as male_ratio
from MyTable t
group by t.state;

我希望這將是幾乎所有數據庫中最快的方法。

是 SQL 小提琴。

您可以通過從每個 state 的總計數中減去男性人數來計算女性人數。 這樣,只需要一個join

with r as (select t.state s, count(*) c from testtable t group by t.state)
select r1.s, t1.m males, r1.c - t1.m females, r1.c total, 100*(t1.m/r1.c) m_percent 
from r r1 
join (select t.state s, t.sex, count(*) m from testtable t group by t.state, t.sex) t1 on r1.s = t1.s where t1.sex = "M"; 

Output:

state 男性 女性 全部的 m_percent
遺傳算法 2 3 5 40.0000
紐約 4 5 9 44.4444

演示

沒有必要將數據分離到MaleFemale的表中。 從性能的角度來看,如果子查詢能夠以最佳方式使用索引,則可能有助於提高性能,但實際上您僅對索引值進行聚合的可能性很小。

對於這個簡單的查詢,您可以使用簡單的CASE表達式內聯將Male / Female列表示為BIT值,然后我們可以在單個聚合中對這些值求和,但是這需要您為Male定義CASE兩次,因此您可以使用它在Male列和% Male中。

我們可以使用CROSS APPLY代替內聯CASE作為對每一行解析一次計算的方法,並允許您引用結果:

SELECT t.state State, 
SUM(Calcs.IsMale) Male, 
SUM(Calcs.IsFemale) Female, 
COUNT(1) Total,
CONCAT(ROUND(SUM(Calcs.IsMale)/CAST(COUNT(1) as float)*100, 2), '%') as Calc
FROM MyTable t
CROSS APPLY (SELECT 
     CASE Sex WHEN 'M' THEN 1 END as [IsMale]
    ,CASE Sex WHEN 'F' THEN 1 END as [IsFemale]
) as calcs
GROUP BY [State]

這是否更有效? 一般來說,這個執行計划應該比加入多個聚合集簡單得多,但是如果沒有更大的數據集來測試它,就很難說。

無論哪種方式,我都希望這個簡單的 CROSS 應用版本能夠獲勝,因為我們只需要處理一次結果集。

在給定數據集上運行原始和 CROSS APPLY 並查看實際執行計划時,SQL Sever 報告 CROSS APPLY 查詢為批處理相對成本的 25%:

我提前道歉將其作為圖片發布,不確定是否有更好的方式進行討論

執行計划,OP 嵌套連接與交叉應用

這個執行計划報告說 Original Query 是 CROSS APPLY 版本的成本的 3 倍,這可能是由於第一個查詢中的 3 次掃描,而 CROSS APPLY 版本中的單表掃描

暫無
暫無

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

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