了解具有许多子查询的大型复杂 SQL 查询的最佳方法
Best way to understand big and complex SQL queries with many subqueries
我刚开始一个新项目,在一家新公司。
我得到了一个大而复杂的 SQL,大约有 1000 行和许多子查询、连接、求和、分组等
此 SQL 用于报告生成(它没有插入或更新)。
SQL 有一些缺陷,我在公司的第一份工作是识别并纠正这些缺陷,以便报告显示正确的值(我通过访问一个写在Cobol...)
如何让我更容易理解查询,以便识别缺陷?
作为一名经验丰富的 Java 程序员,我知道如何用小块代码将复杂的、糟糕的、单一的 Java 代码重构为更容易理解的代码。但我不知道如何用 SQL.
做到这一点
SQL 看起来像这样:
SELECT columns
FROM
(SELECT columns
FROM
(SELECT DISTINCT columns
FROM table000 alias000
INNER JOIN
table000 alias000
ON column000 = table000.column000
LEFT JOIN
(SELECT columns
FROM (
SELECT DISTINCT columns
FROM columns
WHERE conditions) AS alias000
GROUP BY columns ) alias000
ON
conditions
WHERE conditions
) AS alias000
LEFT JOIN
(SELECT
columns
FROM many_tables
WHERE many_conditions
) )
) AS alias000
ON condition
LEFT JOIN (
SELECT columns
FROM
(SELECT
columns
FROM
many_tables
WHERE many_conditions
) ) ) AS alias001
,
(SELECT
many_columns
FROM
many_tables
WHERE many_conditions) AS alias001
) AS alias001
ON condition
LEFT JOIN
(SELECT
many_columns
FROM many_tables
WHERE many_conditions
) AS alias001
ON condition
,
(SELECT DISTINCT columns
FROM table001 alias001
INNER JOIN
table001 alias001
ON condition
LEFT JOIN
(SELECT columns
FROM (
SELECT DISTINCT columns
FROM tables
WHERE conditions
) AS alias001
GROUP BY
columns ) alias001
ON
condition
WHERE
conditions
) AS alias001
LEFT JOIN
(SELECT columns
FROM tables
WHERE conditions
) AS alias001
ON condition
LEFT JOIN (
SELECT columns
FROM
(SELECT columns
FROM tables
WHERE conditions ) AS alias001
,
(SELECT
columns
FROM
tables
WHERE conditions ) AS alias001
) AS alias001
ON condition
LEFT JOIN
(SELECT
columns
FROM
tables
WHERE conditions
) AS alias001
ON condition
WHERE
condition
) AS alias001
order by column001
如何让我更容易理解查询,以便识别缺陷?
编辑:我对这个答案投了反对票,可能是因为他们认为我提议将此作为构建最终查询的方式。我应该澄清一下,这纯粹是为了尝试了解正在发生的事情。一旦您理解了子查询以及它们如何 link 在一起,您就可以使用这些知识对查询进行必要的更改并以有效的方式重建它。
我已经使用中间温度技术 tables 对复杂查询进行了相当多的故障排除。它们将逻辑分解成更小的块,如果原始查询需要很长时间,它们也很有用。您可以测试如何组合这些中间 tables 而无需重新运行整个查询的开销。有时我会使用临时视图而不是 temp tables,因为查询优化器可以继续使用基础 tables 上的索引。临时视图将在您完成后删除。
我会从最里面的子查询开始,一直到外面。
您正在寻找以略有不同的形式多次出现的子查询,并为它们提供简明的描述 - 它们的设计目的是什么?
例如,替换
from (
select x1.y1, x1.y2, x1.y3 ...
from tb1, tb2, tb3, tb4, tb5 ...
left join ...
where ...
group by ...
) as a1
和
from daniel_view1 as a1
其中 daniel_view1
是
create view daniel_view as
select x1.y1, x1.y2, x1.y3 ...
from tb1, tb2, tb3, tb4, tb5 ...
left join ...
where ...
group by ...
这已经使它看起来更干净了。然后比较意见。可以合并在一起吗?您不一定会在最终产品中保留视图,但它们将有助于看到更广泛的模式,而不会淹没细节。
或者,您可以将子查询插入临时 table
insert #daniel_work1
select x1.y1, x1.y2, x1.y3 ...
from tb1, tb2, tb3, tb4, tb5 ...
left join ...
where ...
group by ...
然后将子查询替换为
select ... from #daniel_work1 as a1
您可以做的另一件事是查看是否可以将其分解为连续的步骤。
如果你看到
select ... from ...
union all
select ... from ...
这可能会变成
insert #steps
select 'step1', ...#1...
insert #steps
select 'step2', ...#2...
union
比较棘手,因为 set union 会删除重复的行(所有列都与另一行相同的行)。
通过将中间结果存储在临时 tables 中,您可以在查询展开时查看其内部,并重播困难的步骤。我将 'step_id' 作为我所有调试温度 table 的第一列,因此如果它分阶段填充,那么您会看到哪些数据适用于哪个阶段。
有一些技巧可以提供有关正在发生的事情的线索。如果您看到 table 像这样连接到自身:
select ... from mytable t1 inner join mytable t2 on t2.id < t.id
这通常意味着他们想要 table 与自身的叉积,但没有重复项。您将获得密钥 1 和 2,但不会获得密钥 2 和 1。
从中间开始工作在 SQL 中很常见,将 sql 的基于集合的逻辑转换为顺序逻辑可能会导致性能问题。尽量避免这种情况,尽管我知道这样做很诱人。
我要做的第一件事就是质疑连接语法。这真的是现在写的方式吗?
select
from tb1, tb2, tb3, tb4, tb5 ...
left join ...
from 子句应如下所示
From tb1
Inner join tb2 on .....
Inner join tb3 on .....
....
Left join
http://www-03.ibm.com/software/products/en/data-studio
IBM 提供了一个基于 Eclipse 的分析工具,该工具能够为复杂查询生成可视化 EXPLAIN
图。它显示了索引的使用方式、生成和组合的内部结果集等。
示例:
SELECT * FROM EMPLOYEE, DEPARTMENT WHERE WORKDEPT=DEPTNO
我每天都在处理这样的代码,因为我们在这里进行大量的报告和复杂数据的导出。
第一步是理解你所做的事情的意义。如果你不理解意义,你就无法评价你是否得到了正确的结果。因此,准确了解您要完成的任务,看看您是否可以在用户界面中看到一条记录应该看到的结果。有一些东西可以比较确实很有帮助,这样您就可以在查询过程中看到添加新事物如何改变结果。如果您的查询使用了单个字母或其他对派生的 table 别名无意义的东西,那么当您弄清楚派生的 table 应该做的事情的含义时,然后用更多的东西替换别名像 Employees 而不是 A 一样有意义。这将使下一个处理它的人以后更容易对其进行解码。
然后你要做的是从最内层的派生 table 开始(或者如果你愿意,可以从子查询开始,但是当它被用作 table 时,术语派生 table 更多准确的)。首先弄清楚它应该做什么。例如,也许它正在让所有绩效评估不尽如人意的员工。
运行 然后根据您所做的事情检查结果,看它们是否正确。例如,如果您正在查看不令人满意的评估并且您有 10,000 名员工,5617 似乎是该数据块的合理结果集吗?查找重复的记录。如果同一个人在那里三次,那么当你只想要一个时,你可能会遇到问题,你要加入一对多并取回许多。这可以通过使用聚合函数和分组依据或放入另一个派生 table 来替换问题连接来解决。
一旦你清除了最里面的部分,然后开始检查其他派生的 table 的结果,重新添加代码并检查结果,直到你找到不应该丢失的记录有(嘿,我在这个阶段有 137 名员工,现在只有 116 名。是什么原因造成的?)请记住,这只是了解为什么会发生这种情况的线索。当您构建复杂的查询时,有时基本结果会发生变化,有时它们不应该发生变化,这就是理解数据的含义至关重要的原因。
一般需要注意的一些事项:
- 空值的处理方式会影响结果
- 混合使用隐式连接和显式连接可能会在某些情况下导致不正确的结果
数据库。
- 无论如何,您应该始终将所有隐式连接替换为
明确的。这使得代码更清晰并且不太可能有
错误。
- 如果您有隐式联接,请查找意外交叉联接。他们是
即使在简短的查询中也很容易引入,在复杂的查询中,它们
更有可能,这就是为什么永远不应该使用隐式连接
用过。
如果您离开了加入,请注意他们得到的地方
通过放置 where 子句意外转换为内部连接
左连接 table (除了 id 是否为空)。所以这
结构有问题:
FROM table1 t1
LEFT JOIN Table2 t2 ON t1.t1id = T2.t1id
WHERE t2.somefield = 'test'
应该是
FROM table1 t1
LEFT JOIN Table2 t2 ON t1.t1id = T2.t1id
AND t2.somefield = 'test'
解决方案是使用 COMMON TABLE EXPRESSIONS 来简化查询。
这使我能够将大而复杂的 SQL 查询分解为许多小且易于理解的查询。
常见TABLE 表达式:
- 可用于分解复杂的查询,尤其是复杂的连接和子查询
- 是一种封装查询定义的方式。
- 只坚持到下一个查询是 运行。
- 正确使用可以提高代码 quality/maintainability 和速度。
- 可用于在同一语句中多次引用结果 table(消除 SQL 中的重复)。
- 当不需要视图的一般用途时,可以替代视图;也就是说,您不必将定义存储在元数据中。
示例:
WITH cte (Column1, Column2, Column3)
AS
(
SELECT Column1, Column2, Column3
FROM SomeTable
)
SELECT * FROM cte
我的新 SQL 看起来像这样:
------------------------------------------
--COMMON TABLE EXPRESSION 001--
------------------------------------------
WITH alias001 (column001, column002) AS (
SELECT column005, column006
FROM table001
WHERE condition001
GROUP by column008
)
--------------------------------------------
--COMMON TABLE EXPRESSION 002 --
--------------------------------------------
, alias002 (column009) as (
select distinct column009 from table002
)
--------------------------------------------
--COMMON TABLE EXPRESSION 003 --
--------------------------------------------
, alias003 (column1, column2, column3) as (
SELECT '1' AS column1, '1' as column2, 'name001' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '1' AS column1, '1.1' as column2, 'name002' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '1' AS column1, '1.2' as column2, 'name003' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '2' AS column1, '2' as column2, 'name004' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '2' AS column1, '2.1' as column2, 'name005' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '2' AS column1, '2.2' as column2, 'name006' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '3' AS column1, '3' as column2, 'name007' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '3' AS column1, '3.1' as column2, 'name008' AS column3 FROM SYSIBM.SYSDUMMY1
)
--------------------------------------------
--COMMON TABLE EXPRESSION 004 --
--------------------------------------------
, alias004 (column1) as (
select distinct column1 from table003
)
------------------------------------------------------
--COMMON TABLE EXPRESSION 005 --
------------------------------------------------------
, alias005 (column1, column2) as (
select column1, column2 from alias002, alias004
)
------------------------------------------------------
--COMMON TABLE EXPRESSION 006 --
------------------------------------------------------
, alias006 (column1, column2, column3, column4) as (
SELECT column1, column2, column3, sum(column0) as column4
FROM table004
LEFT JOIN table005 ON column01 = column02
group by column1, column2, column3
)
------------------------------------------------------
--COMMON TABLE EXPRESSION 007 --
------------------------------------------------------
, alias007 (column1, column2, column3, column4) as (
SELECT column1, column2, column3, sum(column0) as column4
FROM table006
LEFT JOIN table007 ON column01 = column02
group by column1, column2, column3
)
------------------------------------------------------
--COMMON TABLE EXPRESSION 008 --
------------------------------------------------------
, alias008 (column1, column2, column3, column4) as (
select column1, column2, column3, column4 from alias007 where column5 = 123
)
----------------------------------------------------------
--COMMON TABLE EXPRESSION 009 --
----------------------------------------------------------
, alias009 (column1, column2, column3, column4) as (
select column1, column2,
CASE WHEN column3 IS NOT NULL THEN column3 ELSE 0 END as column3,
CASE WHEN column4 IS NOT NULL THEN column4 ELSE 0 END as column4
from table007
)
----------------------------------------------------------
--COMMON TABLE EXPRESSION 010 --
----------------------------------------------------------
, alias010 (column1, column2, column3) as (
select column1, sum(column4), sum(column5)
from alias009
where column6 < 2005
group by column1
)
--------------------------------------------
-- MAIN QUERY --
--------------------------------------------
select j.column1, n.column2, column3, column4, column5, column6,
column3 + column5 AS column7,
column4 + column6 AS column8
from alias010 j
left join alias006 m ON (m.column1 = j.column1)
left join alias008 n ON (n.column1 = j.column1)
我刚开始一个新项目,在一家新公司。
我得到了一个大而复杂的 SQL,大约有 1000 行和许多子查询、连接、求和、分组等
此 SQL 用于报告生成(它没有插入或更新)。
SQL 有一些缺陷,我在公司的第一份工作是识别并纠正这些缺陷,以便报告显示正确的值(我通过访问一个写在Cobol...)
如何让我更容易理解查询,以便识别缺陷?
作为一名经验丰富的 Java 程序员,我知道如何用小块代码将复杂的、糟糕的、单一的 Java 代码重构为更容易理解的代码。但我不知道如何用 SQL.
做到这一点SQL 看起来像这样:
SELECT columns
FROM
(SELECT columns
FROM
(SELECT DISTINCT columns
FROM table000 alias000
INNER JOIN
table000 alias000
ON column000 = table000.column000
LEFT JOIN
(SELECT columns
FROM (
SELECT DISTINCT columns
FROM columns
WHERE conditions) AS alias000
GROUP BY columns ) alias000
ON
conditions
WHERE conditions
) AS alias000
LEFT JOIN
(SELECT
columns
FROM many_tables
WHERE many_conditions
) )
) AS alias000
ON condition
LEFT JOIN (
SELECT columns
FROM
(SELECT
columns
FROM
many_tables
WHERE many_conditions
) ) ) AS alias001
,
(SELECT
many_columns
FROM
many_tables
WHERE many_conditions) AS alias001
) AS alias001
ON condition
LEFT JOIN
(SELECT
many_columns
FROM many_tables
WHERE many_conditions
) AS alias001
ON condition
,
(SELECT DISTINCT columns
FROM table001 alias001
INNER JOIN
table001 alias001
ON condition
LEFT JOIN
(SELECT columns
FROM (
SELECT DISTINCT columns
FROM tables
WHERE conditions
) AS alias001
GROUP BY
columns ) alias001
ON
condition
WHERE
conditions
) AS alias001
LEFT JOIN
(SELECT columns
FROM tables
WHERE conditions
) AS alias001
ON condition
LEFT JOIN (
SELECT columns
FROM
(SELECT columns
FROM tables
WHERE conditions ) AS alias001
,
(SELECT
columns
FROM
tables
WHERE conditions ) AS alias001
) AS alias001
ON condition
LEFT JOIN
(SELECT
columns
FROM
tables
WHERE conditions
) AS alias001
ON condition
WHERE
condition
) AS alias001
order by column001
如何让我更容易理解查询,以便识别缺陷?
编辑:我对这个答案投了反对票,可能是因为他们认为我提议将此作为构建最终查询的方式。我应该澄清一下,这纯粹是为了尝试了解正在发生的事情。一旦您理解了子查询以及它们如何 link 在一起,您就可以使用这些知识对查询进行必要的更改并以有效的方式重建它。
我已经使用中间温度技术 tables 对复杂查询进行了相当多的故障排除。它们将逻辑分解成更小的块,如果原始查询需要很长时间,它们也很有用。您可以测试如何组合这些中间 tables 而无需重新运行整个查询的开销。有时我会使用临时视图而不是 temp tables,因为查询优化器可以继续使用基础 tables 上的索引。临时视图将在您完成后删除。
我会从最里面的子查询开始,一直到外面。 您正在寻找以略有不同的形式多次出现的子查询,并为它们提供简明的描述 - 它们的设计目的是什么?
例如,替换
from (
select x1.y1, x1.y2, x1.y3 ...
from tb1, tb2, tb3, tb4, tb5 ...
left join ...
where ...
group by ...
) as a1
和
from daniel_view1 as a1
其中 daniel_view1
是
create view daniel_view as
select x1.y1, x1.y2, x1.y3 ...
from tb1, tb2, tb3, tb4, tb5 ...
left join ...
where ...
group by ...
这已经使它看起来更干净了。然后比较意见。可以合并在一起吗?您不一定会在最终产品中保留视图,但它们将有助于看到更广泛的模式,而不会淹没细节。
或者,您可以将子查询插入临时 table
insert #daniel_work1
select x1.y1, x1.y2, x1.y3 ...
from tb1, tb2, tb3, tb4, tb5 ...
left join ...
where ...
group by ...
然后将子查询替换为
select ... from #daniel_work1 as a1
您可以做的另一件事是查看是否可以将其分解为连续的步骤。 如果你看到
select ... from ...
union all
select ... from ...
这可能会变成
insert #steps
select 'step1', ...#1...
insert #steps
select 'step2', ...#2...
union
比较棘手,因为 set union 会删除重复的行(所有列都与另一行相同的行)。
通过将中间结果存储在临时 tables 中,您可以在查询展开时查看其内部,并重播困难的步骤。我将 'step_id' 作为我所有调试温度 table 的第一列,因此如果它分阶段填充,那么您会看到哪些数据适用于哪个阶段。
有一些技巧可以提供有关正在发生的事情的线索。如果您看到 table 像这样连接到自身:
select ... from mytable t1 inner join mytable t2 on t2.id < t.id
这通常意味着他们想要 table 与自身的叉积,但没有重复项。您将获得密钥 1 和 2,但不会获得密钥 2 和 1。
从中间开始工作在 SQL 中很常见,将 sql 的基于集合的逻辑转换为顺序逻辑可能会导致性能问题。尽量避免这种情况,尽管我知道这样做很诱人。
我要做的第一件事就是质疑连接语法。这真的是现在写的方式吗?
select
from tb1, tb2, tb3, tb4, tb5 ...
left join ...
from 子句应如下所示
From tb1
Inner join tb2 on .....
Inner join tb3 on .....
....
Left join
http://www-03.ibm.com/software/products/en/data-studio
IBM 提供了一个基于 Eclipse 的分析工具,该工具能够为复杂查询生成可视化 EXPLAIN
图。它显示了索引的使用方式、生成和组合的内部结果集等。
示例:
SELECT * FROM EMPLOYEE, DEPARTMENT WHERE WORKDEPT=DEPTNO
我每天都在处理这样的代码,因为我们在这里进行大量的报告和复杂数据的导出。
第一步是理解你所做的事情的意义。如果你不理解意义,你就无法评价你是否得到了正确的结果。因此,准确了解您要完成的任务,看看您是否可以在用户界面中看到一条记录应该看到的结果。有一些东西可以比较确实很有帮助,这样您就可以在查询过程中看到添加新事物如何改变结果。如果您的查询使用了单个字母或其他对派生的 table 别名无意义的东西,那么当您弄清楚派生的 table 应该做的事情的含义时,然后用更多的东西替换别名像 Employees 而不是 A 一样有意义。这将使下一个处理它的人以后更容易对其进行解码。
然后你要做的是从最内层的派生 table 开始(或者如果你愿意,可以从子查询开始,但是当它被用作 table 时,术语派生 table 更多准确的)。首先弄清楚它应该做什么。例如,也许它正在让所有绩效评估不尽如人意的员工。
运行 然后根据您所做的事情检查结果,看它们是否正确。例如,如果您正在查看不令人满意的评估并且您有 10,000 名员工,5617 似乎是该数据块的合理结果集吗?查找重复的记录。如果同一个人在那里三次,那么当你只想要一个时,你可能会遇到问题,你要加入一对多并取回许多。这可以通过使用聚合函数和分组依据或放入另一个派生 table 来替换问题连接来解决。
一旦你清除了最里面的部分,然后开始检查其他派生的 table 的结果,重新添加代码并检查结果,直到你找到不应该丢失的记录有(嘿,我在这个阶段有 137 名员工,现在只有 116 名。是什么原因造成的?)请记住,这只是了解为什么会发生这种情况的线索。当您构建复杂的查询时,有时基本结果会发生变化,有时它们不应该发生变化,这就是理解数据的含义至关重要的原因。
一般需要注意的一些事项:
- 空值的处理方式会影响结果
- 混合使用隐式连接和显式连接可能会在某些情况下导致不正确的结果 数据库。
- 无论如何,您应该始终将所有隐式连接替换为 明确的。这使得代码更清晰并且不太可能有 错误。
- 如果您有隐式联接,请查找意外交叉联接。他们是 即使在简短的查询中也很容易引入,在复杂的查询中,它们 更有可能,这就是为什么永远不应该使用隐式连接 用过。
如果您离开了加入,请注意他们得到的地方 通过放置 where 子句意外转换为内部连接 左连接 table (除了 id 是否为空)。所以这 结构有问题:
FROM table1 t1 LEFT JOIN Table2 t2 ON t1.t1id = T2.t1id WHERE t2.somefield = 'test'
应该是
FROM table1 t1 LEFT JOIN Table2 t2 ON t1.t1id = T2.t1id AND t2.somefield = 'test'
解决方案是使用 COMMON TABLE EXPRESSIONS 来简化查询。
这使我能够将大而复杂的 SQL 查询分解为许多小且易于理解的查询。
常见TABLE 表达式:
- 可用于分解复杂的查询,尤其是复杂的连接和子查询
- 是一种封装查询定义的方式。
- 只坚持到下一个查询是 运行。
- 正确使用可以提高代码 quality/maintainability 和速度。
- 可用于在同一语句中多次引用结果 table(消除 SQL 中的重复)。
- 当不需要视图的一般用途时,可以替代视图;也就是说,您不必将定义存储在元数据中。
示例:
WITH cte (Column1, Column2, Column3)
AS
(
SELECT Column1, Column2, Column3
FROM SomeTable
)
SELECT * FROM cte
我的新 SQL 看起来像这样:
------------------------------------------
--COMMON TABLE EXPRESSION 001--
------------------------------------------
WITH alias001 (column001, column002) AS (
SELECT column005, column006
FROM table001
WHERE condition001
GROUP by column008
)
--------------------------------------------
--COMMON TABLE EXPRESSION 002 --
--------------------------------------------
, alias002 (column009) as (
select distinct column009 from table002
)
--------------------------------------------
--COMMON TABLE EXPRESSION 003 --
--------------------------------------------
, alias003 (column1, column2, column3) as (
SELECT '1' AS column1, '1' as column2, 'name001' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '1' AS column1, '1.1' as column2, 'name002' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '1' AS column1, '1.2' as column2, 'name003' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '2' AS column1, '2' as column2, 'name004' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '2' AS column1, '2.1' as column2, 'name005' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '2' AS column1, '2.2' as column2, 'name006' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '3' AS column1, '3' as column2, 'name007' AS column3 FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT '3' AS column1, '3.1' as column2, 'name008' AS column3 FROM SYSIBM.SYSDUMMY1
)
--------------------------------------------
--COMMON TABLE EXPRESSION 004 --
--------------------------------------------
, alias004 (column1) as (
select distinct column1 from table003
)
------------------------------------------------------
--COMMON TABLE EXPRESSION 005 --
------------------------------------------------------
, alias005 (column1, column2) as (
select column1, column2 from alias002, alias004
)
------------------------------------------------------
--COMMON TABLE EXPRESSION 006 --
------------------------------------------------------
, alias006 (column1, column2, column3, column4) as (
SELECT column1, column2, column3, sum(column0) as column4
FROM table004
LEFT JOIN table005 ON column01 = column02
group by column1, column2, column3
)
------------------------------------------------------
--COMMON TABLE EXPRESSION 007 --
------------------------------------------------------
, alias007 (column1, column2, column3, column4) as (
SELECT column1, column2, column3, sum(column0) as column4
FROM table006
LEFT JOIN table007 ON column01 = column02
group by column1, column2, column3
)
------------------------------------------------------
--COMMON TABLE EXPRESSION 008 --
------------------------------------------------------
, alias008 (column1, column2, column3, column4) as (
select column1, column2, column3, column4 from alias007 where column5 = 123
)
----------------------------------------------------------
--COMMON TABLE EXPRESSION 009 --
----------------------------------------------------------
, alias009 (column1, column2, column3, column4) as (
select column1, column2,
CASE WHEN column3 IS NOT NULL THEN column3 ELSE 0 END as column3,
CASE WHEN column4 IS NOT NULL THEN column4 ELSE 0 END as column4
from table007
)
----------------------------------------------------------
--COMMON TABLE EXPRESSION 010 --
----------------------------------------------------------
, alias010 (column1, column2, column3) as (
select column1, sum(column4), sum(column5)
from alias009
where column6 < 2005
group by column1
)
--------------------------------------------
-- MAIN QUERY --
--------------------------------------------
select j.column1, n.column2, column3, column4, column5, column6,
column3 + column5 AS column7,
column4 + column6 AS column8
from alias010 j
left join alias006 m ON (m.column1 = j.column1)
left join alias008 n ON (n.column1 = j.column1)