当SELECT后面的子查询不能被删除?
Posted
技术标签:
【中文标题】当SELECT后面的子查询不能被删除?【英文标题】:When subquery behind SELECT can not be removed? 【发布时间】:2017-11-02 21:16:36 【问题描述】:相关子查询被视为bad habit。我相信任何带有SELECT
和FROM
之间子查询的SQL 命令(我们称之为SELECT 子查询)都可以重写为没有任何子查询的SQL。例如这样的查询
select *,
(
select sum(t2.sales)
from your_table t2
where t2.dates
between t1.dates - interval '3' day and
t1.dates and
t2.id = t1.id
) running_sales
from your_table t1
demo
可以改写成下面一个
select dd.id, dd.dates, dd.sales, sum(d.sales) running_sales
from your_table dd
join your_table d on d.dates
between (dd.dates - interval '3' day) and
dd.dates and
dd.id = d.id
group by dd.id, dd.dates, dd.sales
demo
当有多个SELECT子查询时可能会出现问题,但是即使在这种情况下,也可以将它们重写为FROM
后面的子查询,然后按照以下精神执行LEFT JOIN
select *,
(
select sum(sales)
from dat dd
where dd.dates
between (d.dates - interval '3' day) and d.dates and
dd.id = d.id
) running_sales,
(
select sum(sales)
from dat dd
where dd.id = d.id
) total_sales
from dat d
demo
可以改写成下面一个
select d.*,
t_running.running_sales,
t_total.total_sales
from dat d
left join (
select dd.id, dd.dates, sum(d.sales) running_sales
from dat dd
join dat d on d.dates
between (dd.dates - interval '3' day) and
dd.dates and
dd.id = d.id
group by dd.id, dd.dates
) t_running on d.id = t_running.id and d.dates = t_running.dates
left join (
select d.id, sum(d.sales) total_sales
from dat d
group by d.id
) t_total on t_total.id = d.id
demo
您能否提供一个示例,说明 不可能 摆脱 SELECT 子查询?请善待并添加一个工作示例链接(例如dbfiddle 或sqlfiddle)以使潜在的讨论更容易,谢谢!
【问题讨论】:
我真的不知道这是否是 SE 的主题?...无论如何,我会给出“不”的答案,select 语句中的子查询总是可以用更好的方式。 我同意,这是题外话。也就是说,有时为了清楚起见,使用子查询是合适的。我的主数据库是 Oracle,而不是你标签中的 SQL*Server,但是我已经在 Oracle 上编写了两种查询方式并且收到了相同的解释计划,所以它在性能方面没有任何区别。 @BrianLeach 好的,为什么它被认为是一个坏习惯呢?我在比提供的链接更多的地方阅读了这样的意见。 它们总是可以轻松地交换到外部应用中。前 N 个子查询不能被重写为一个连接,尽管没有彻底重写以使用不同的结构,例如行号。 我同意这通常是个坏主意。我看到它以有效方式使用的唯一地方是从 CRM 数据库中检索数据的情况,该数据库在过滤视图上使用行级安全性。在选择子查询中检索查找数据减少了需要检查安全性的记录数量并显着提高了性能。然而,每当我看到其中一个查询时,我仍然会畏缩。 【参考方案1】:如果问题是针对多项选择测试(或类似的测试):),则无法摆脱 EXISTS
子句的子查询。
另一个类似的答案是 IN (subquery)
用于不同级别的聚合以避免笛卡尔积。
(顺便说一句:相关的子查询并不是每次都认为是一个坏习惯,它取决于优化、结构等......
WITH
是一种相关子查询的使用...对于复杂的查询非常实用。 )
【讨论】:
以上是关于当SELECT后面的子查询不能被删除?的主要内容,如果未能解决你的问题,请参考以下文章