调整查询以使用CTE

时间:2019-01-31 02:02:24

标签: sql postgresql common-table-expression query-performance

我正在寻找在查询中使用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;

3 个答案:

答案 0 :(得分:0)

为每个子查询使用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;

答案 1 :(得分:0)

尝试此查询:

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 :(得分:-1)

我将仅提供关于该问题本身的切线。

我强烈建议您完全不使用CTE 。如果您希望有一个看起来不错的优雅查询,我相信将查询格式正确设置会更好。 http://www.dpriver.com/pp/sqlformat.htm

的CTE有被作为某种方式索引慢没有正确触发的大部分时间的固有问题。我从事SQL多年,因此在CTE中遇到了很多性能问题。提高CTE的速度是困难的,我认为这是不值得的。他们使调试和测试查询痛苦太特别是当有大量的CTE表。很难将子查询区分开,尤其是测试先前子查询的假设是否仍然有效时。

您还可以在stackoverflow中检查至少500多个有关CTE缓慢的问题: https://stackoverflow.com/search?q=slow+cte

我的建议是将数据放在临时表中。您也可以通过仅重复使用临时表来删除重复的代码。为了更好地提高性能,您可以在临时表中添加索引。不能创建在热膨胀系数飞索引。为什么在我看来,使用CTE的唯一理由是递归的CTE。 https://www.essentialsql.com/recursive-ctes-explained/