[英]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
我希望结果是:
我正在使用的查询是:
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 |
见演示。
没有必要将数据分离到Male和Female的表中。 从性能的角度来看,如果子查询能够以最佳方式使用索引,则可能有助于提高性能,但实际上您仅对索引值进行聚合的可能性很小。
对于这个简单的查询,您可以使用简单的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%:
我提前道歉将其作为图片发布,不确定是否有更好的方式进行讨论
这个执行计划报告说 Original Query 是 CROSS APPLY 版本的成本的 3 倍,这可能是由于第一个查询中的 3 次表扫描,而 CROSS APPLY 版本中的单表扫描。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.