调整查询以使用 CTE
Posted
技术标签:
【中文标题】调整查询以使用 CTE【英文标题】:Adapting query to use CTE 【发布时间】:2019-01-31 02:02:24 【问题描述】:我正在寻找在查询中使用 CTE,因为我得到了相同的选择,但我以前从未使用过 CTE,有人可以帮助我吗?
我需要 firstTable 可以在其他选择中使用
SELECT firstTable.id as id,
secondTable.holder as holder
FROM (
select tb3.id as id
from table1 tb1
inner join table2 tb2 on tb1.tb2_id = tb2.id
inner join table3 tb3 on tb2.tb3_id = tb3.id and tb3.id
inner join table4 tb4 on tb4.id = tb3.tb4_id and tb4.id = 1998
group by tb3.id) as firstTable
JOIN (
select id_holder,
sum(temporaryTable.holder) as holder
from (
select cast(tb4.helper as integer) as helper,
count(distinct tb4.id) as holder,
tb3.id as id_holder
from table1 tb1
inner join table2 tb2 on tb1.tb2_id = tb2.id
inner join table3 tb3 on tb2.tb3_id = tb3.id and tb3.id
inner join table4 tb4 on tb4.id = tb3.tb4_id and tb4.id = 1998
group by tb3.id, tb4.helper
) as temporaryTable
where temporaryTable.helper between 7 and 8
group by id_holder) as secondTable
ON firstTable.id = temporaryTable.id_holder
这是我的尝试查询:
WITH temporary_table AS
( SELECT id,
cast(resp.valor AS integer) AS holder,
count(val) AS sumId
FROM table1 tb1
INNER JOIN table2 tb2 ON tb1.tb2_id = tb2.id
INNER JOIN table3 tb3 ON tb2.tb3_id = tb3.id
AND tb3.id
INNER JOIN table4 tb4 ON tb4.id = tb3.tb4_id
AND tb4.id = 1998
GROUP BY tb3.id )
SELECT
(SELECT SUM(sumId)
WHERE holder = -10) AS p1,
(SELECT SUM(sumId)
WHERE holder = 78) AS p2,
(SELECT SUM(sumId)
WHERE holder = 1997) AS p3,
id
FROM temporary_table
GROUP BY id,
holder;
【问题讨论】:
可以参考CTE
docpostgresql.org/docs/9.1/queries-with.html
我是,但我不能把我的“where”子句放在最后:/它不起作用
如果你在这里发布你的no working
会更好。我们很高兴帮助您解决这个问题,而不仅仅是为您编写所有这些 cte
@PhamX.Bach 我会编辑问题
您的CTE
查询似乎不等于您的第一个查询。即使您不使用CTE
,您的SELECT (select SUM(sumId) where holder = -10) as p1,
也将不起作用。您应该将其更改为 SELECT SUM(CASE WHEN holder = -10 THEN sumId END) AS p1,
而不是按持有者分组
【参考方案1】:
试试这个查询:
select tb3.id as id,
count(distinct CASE WHEN tb4.helper between 7 and 8 THEN tb4.id END) as holder,
from table1 tb1
inner join table2 tb2 on tb1.tb2_id = tb2.id
inner join table3 tb3 on tb2.tb3_id = tb3.id and tb3.id
inner join table4 tb4 on tb4.id = tb3.tb4_id and tb4.id = 1998
group by tb3.id
【讨论】:
【参考方案2】:对每个子查询使用 CTE 非常简单:
WITH firstTable AS (
select tb3.id as id
from table1 tb1
inner join table2 tb2 on tb1.tb2_id = tb2.id
inner join table3 tb3 on tb2.tb3_id = tb3.id and tb3.id
inner join table4 tb4 on tb4.id = tb3.tb4_id and tb4.id = 1998
group by tb3.id
), temporaryTable AS (
select cast(tb4.helper as integer) as helper,
count(distinct tb4.id) as holder,
tb3.id as id_holder
from table1 tb1
inner join table2 tb2 on tb1.tb2_id = tb2.id
inner join table3 tb3 on tb2.tb3_id = tb3.id and tb3.id
inner join table4 tb4 on tb4.id = tb3.tb4_id and tb4.id = 1998
group by tb3.id, tb4.helper
), secondTable AS (
select id_holder,
sum(temporaryTable.holder) as holder
from temporaryTable
where temporaryTable.helper between 7 and 8
group by id_holder
)
SELECT firstTable.id as id,
secondTable.holder as holder
FROM firstTable
JOIN secondTable
ON firstTable.id = temporaryTable.id_holder;
【讨论】:
谢谢!它比另一个更具有性能,对吧? CTE 可以帮助提高查询的可读性,但不会加快查询速度。如果有的话,我在我的经验中看到,就像其他答案一样,索引并不总是在您期望的时候得到正确利用。为了提高性能,请考虑额外的索引或临时表是否有用。 @t9217:有时 CTE 使事情变得更快,有时它们使事情变慢,有时它们对性能没有任何影响。找出答案的唯一方法是为每个版本运行explain (analyze)
并亲自查看。【参考方案3】:
我将仅提供问题本身的切线。
我强烈建议您不要使用 CTE。如果您想要一个看起来不错的优雅查询,我相信正确格式化您的查询会更好。 http://www.dpriver.com/pp/sqlformat.htm
CTE 有一个固有的问题是速度很慢,因为在大多数情况下索引都没有正确触发。多年来,我一直从事 SQL 作为职业,在 CTE 中遇到了很多性能问题。使 CTE 更快是困难的,我认为不值得付出努力。它们也使调试和测试查询变得很痛苦,尤其是当 CTE 中有很多表时。很难划分子查询,尤其是测试前一个子查询的假设是否仍然有效。
您还可以在 *** 中查看以下至少 500 多个关于 CTE 速度慢的问题: https://***.com/search?q=slow+cte
我的建议是将数据放在临时表中。您还可以通过重用临时表来删除重复的代码。作为获得更好性能的额外奖励,您可以在临时表中创建索引。您不能在 CTE 中动态创建索引。在我看来,使用 CTE 的唯一原因是递归 CTE。 https://www.essentialsql.com/recursive-ctes-explained/
【讨论】:
以上是关于调整查询以使用 CTE的主要内容,如果未能解决你的问题,请参考以下文章
无法计算 CTE 子查询输出之间的差异以用于更大的 PostgreSQL 查询输出列