如何简化多个CTE

huangapple go评论57阅读模式
英文:

How to simplify multiple CTE

问题

我有几个类似的CTE,实际上有9个。区别在于子查询中for列的WHERE子句。

在我的数据库是只读的情况下,我无法使用函数。

每个CTE都处理大量的数据记录。

是否有一种方法,可以设置for列的参数或绕过此限制?

英文:

I have several similar CTE, actually 9. The difference is in the WHERE clause from the subquery on the column for.

WITH my_cte_1 AS (
    SELECT  id,
        "time",
        LEAD("time",1) OVER (
            PARTITION BY id
            ORDER BY id,"time"
        ) next_time
    FROM history
    where id IN (SELECT id FROM req WHERE type = 'sup' AND for = 1)
),
WITH my_cte_2 AS (
            SELECT  id,
        "time",
        LEAD("time",1) OVER (
            PARTITION BY id
            ORDER BY id,"time"
        ) next_time
    FROM history
    where id IN (SELECT id FROM req WHERE type = 'sup' AND for = 2)
),
WITH my_cte_3 AS (
            SELECT  id,
        "time",
        LEAD("time",1) OVER (
            PARTITION BY id
            ORDER BY id,"time"
        ) next_time
    FROM history
    where id IN (SELECT id FROM req WHERE type = 'sup' AND for = 3)
) 

SELECT
'History' AS "Indic",
(SELECT count(DISTINCT(id)) FROM my_cte_1 ) AS "cte1",
(SELECT count(DISTINCT(id)) FROM my_cte_2 ) AS "cte2",
(SELECT count(DISTINCT(id)) FROM my_cte_3 ) AS "cte3",

My database is read only so I can't use function.

Each CTE process a large record of data.

Is there a way, where I can setup a parameter for the column for or a workaround ?

答案1

得分: 1

以下是翻译好的部分:

我假设一点,但我认为类似这样的代码会起作用:

    with cte as (
        SELECT
          h.id, h."time",
          LEAD(h."time",1) OVER (PARTITION BY h.id ORDER BY h.id, h."time") next_time,
          r.for
        FROM
          history h
          join req r on
            r.type = 'sup' and
            h.id = r.id and
            r.for between 1 and 3
    )
    select
      'History' AS "Indic",
      count (distinct id) filter (where for = 1) as cte1,
      count (distinct id) filter (where for = 2) as cte2,
      count (distinct id) filter (where for = 3) as cte3
    from cte

这将避免多次访问不同的表,并且应该运行得更快,除非这些值高度选择性。

另一点... "lead" 分析函数似乎没有被使用。如果这真的是你的查询的全部内容,你可以省略它,使查询运行得更快。我保留了它,假设它有其他用途。
英文:

I'm assuming a little bit here, but I would think something like this would work:

with cte as (
    SELECT
      h.id, h."time",
      LEAD(h."time",1) OVER (PARTITION BY h.id ORDER BY h.id, h."time") next_time,
      r.for
    FROM
      history h
      join req r on
        r.type = 'sup' and
        h.id = r.id and
        r.for between 1 and 3
)
select
  'History' AS "Indic",
  count (distinct id) filter (where for = 1) as cte1,
  count (distinct id) filter (where for = 2) as cte2,
  count (distinct id) filter (where for = 3) as cte3
from cte

This would avoid multiple passes on the various tables and should run much quicker unless these are highly selective values.

Another note... the "lead" analytic function doesn't appear to be used. If this is really all there is to your query, you can omit that and make it run a lot faster. I left it in assuming it had some other purpose.

huangapple
  • 本文由 发表于 2023年2月8日 20:42:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75385967.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定