【问题标题】:how to minimize the use of subquery如何最小化子查询的使用
【发布时间】:2020-09-02 08:03:44
【问题描述】:

我有以下表格,我想计算销售数字。我使用了一些子查询来做到这一点。我可以不使用子查询而不使用表变量吗?

表 A,4 列 - 填充 键P |人口 |城市|国家 一些数据 100, 1234, 伦敦, 英国 101, 2345, 牛津, 英国 102, 3345, 布里斯托尔, 英国 103, 1256, 纽约, 美国 104, 5424, 洛杉矶, 美国 105, 100, 北京, 中国 表 B,4 列 - sales_amount 键A |金额 |城市|国家 一些数据 200, 105, 伦敦, 英国 201, 210, 牛津,英国 203, 23, 纽约, 美国 204, 54, 洛杉矶, 美国 第一个表中的城市可能不存在于第二个表中
select aa.country, aa.popu, bb.amou from 
    (select sum(population) as popu, country from population group by country) aa
left join 
    (select sum(amount) as amou, country from sales_amount group by countr) bb
on aa.country = bb.country
子查询 1 将返回 英国, 6924 美国, 6680 中国, 100 子查询 2 将返回 英国,315 美国, 77 最后结果 英国, 6924, 315 美国, 6680, 77, 中国,100,空

这是一个例子。我的真实查询有很多这样的小表,我需要先分组,然后加入进行最终计算。

我不想使用子查询,因为我的真实表有更多的列并且真实的查询非常长。它非常不可读,很难维护。

【问题讨论】:

  • 样本数据和预期结果将帮助我们帮助您。
  • 似乎是一种合理的方法。为什么要改呢?
  • 不过,您可能需要至少一个子查询。
  • 你为什么不加入所有的表并在最后调用一个 groupby 而总是在子查询中做一个 groupby 呢?查询优化器应该足够聪明,能够弄清楚如何有效地做到这一点
  • @Karl:因为这些连接是多对多的,而且总和是完全错误的

标签: sql tsql


【解决方案1】:

您可以执行以下操作将单个查询结果合并为一个,如下所示

select aa.country, aa.popu, bb.amou,cc.smou from 
    (select sum(population) as popu, country from population group by country) aa
inner join 
    (select sum(amount) as amou, country from sales_amount group by countr) bb
on aa.country = bb.country inner join
    (select sum(sales) as smou, country from sales_amount group by countr) cc
on bb.country = cc.country
-- inner join ..  so on as you wrote....

【讨论】:

  • 这与原始查询相同,只是连接的另一种顺序,没有人会使用:-)
  • 好吧,当人们想将来自不同表的结果组合成一个查询结果时,我看不到任何其他选项来读取结果!除了写一个 CTE 或创建一个视图或上面的东西..
【解决方案2】:

编辑,好的,那么为什么不在聚合已经完成的地方创建视图,特别是如果这是您经常使用的信息。如果可读性是您主要关心的问题,那么这应该会有所帮助。例如:

CREATE VIEW vw_aggregated_population AS
SELECT sum(population) AS popu, country 
FROM population GROUP BY country

CREATE VIEW vw_aggregated_sales_amount AS
SELECT sum(amount) AS amou, country 
FROM sales_amount GROUP BY country

紧随其后

SELECT
vw_aggregated_population.country,
popu, 
amou,
FROM vw_aggregated_population
LEFT JOIN vw_aggregated_sales_amount
ON vw_aggregated_population.country=vw_aggregated_sales_amount.country
GROUP BY vw_aggregated_population.country

【讨论】:

  • 因为这些连接是多对多的,而且总和是完全错误的。由于行数呈爆炸式增长,额​​外的性能会很糟糕。
  • 好的,您应该在问题中说明这一点。查看更新的答案
  • 这很明显,为什么要 GROUP BY 已经是 UNIQUE 的列?
  • 你会惊讶于我在 SO 问题中看到了多少这样的事情......
【解决方案3】:

您可以使用full joingroup byunion all 来获取所有表中的所有 行。这是使用第二种方法的示例:

with p as (
      select sum(population) as population, country
      from population
      group by country
     ),
     sa as (
      select sum(amount) as amount, country
      from sales_amount
      group by country
     ) 
select country, max(population), max(amount)
from ((select country, population, null as amount
       from p
      ) union all
      (select country, null, amount
       from sa
      )
     ) ps
group by country;

应该清楚如何为更多表扩展它。

【讨论】:

  • 由于涉及到很多表,我们不知道数据大小。那么,从性能的角度来看,您更喜欢哪个?使用 group by 完全加入或联合所有。
  • @AnkitBajpai 。 . .我使用了union all 方法,因为它更容易泛化。我实际上不确定哪个在 SQL Server 中效果更好。如果您有大量数据,则值得比较性能。与其他 JOINs 相比,FULL JOIN 有一些额外的开销。 GROUP BY 也有开销。但是如果你在每个子表中都有country的索引,那么GROUP BY应该是非常合理的。
猜你喜欢
  • 1970-01-01
  • 2011-04-27
  • 1970-01-01
  • 2021-12-12
  • 2019-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多