【问题标题】:How to escape several with in the query?如何在查询中转义几个 with?
【发布时间】:2021-02-09 03:30:14
【问题描述】:

我需要重构我的查询,但我不知道该怎么做。

我可以看到几个重复使用相同的逻辑,但我不断重复这种查询方式从一个查询到另一个查询,我觉得这种查询成为我思考 SQL 的主要框架,我没有想要这个。

你能告诉我这个查询的更可接受的变体吗,这样我就不再重复我的思维方式了?

在这里

WITH fourth_table AS
(
    WITH third_table AS
    (
        WITH second_table AS
        (
            WITH initial_table AS
            (
                SELECT 
                DISTINCT ctr.country_region, EXTRACT (YEAR FROM s.time_id)::int AS calendar_year, chn.channel_desc, 
                SUM(s.amount_sold) OVER (PARTITION BY ctr.country_region||chn.channel_desc||EXTRACT (YEAR FROM s.time_id)) AS amount_sold
                FROM sales s
                JOIN channels chn ON s.channel_id = chn.channel_id
                JOIN customers c ON s.cust_id  = c.cust_id
                JOIN countries ctr ON c.country_id = ctr.country_id
                WHERE ctr.country_region IN ('Americas','Asia', 'Europe')
                AND
                EXTRACT (YEAR FROM s.time_id)::int IN (1998, 1999, 2000, 2001)
                ORDER BY ctr.country_region, calendar_year, chn.channel_desc
            )
                SELECT country_region, calendar_year, channel_desc, amount_sold,
                (amount_sold/SUM(amount_sold) OVER (PARTITION BY country_region||calendar_year)*100)::decimal(10,2) AS bychannels
                FROM initial_table
        )
        SELECT *,
        LAG (bychannels, 4) OVER (ORDER BY 6) AS lower_salary
        FROM second_table--correct here smth wrong
    )
    SELECT *, bychannels - lower_salary AS diff FROM third_table
)
SELECT country_region, calendar_year, channel_desc, 
--'FM     999,999,999,990D'
LPAD(to_char(amount_sold, 'FM999,999,999,990 $'),20, ' ') AS amount_sold,
LPAD(bychannels || ' %' ,20, ' ') AS "% BY CHANNELS",
LPAD(lower_salary || ' %    ' ,20, ' ') AS "% PREVIOUS PERIOD", 
diff AS "% DIFF"
FROM fourth_table WHERE calendar_year NOT IN (1998);

【问题讨论】:

    标签: sql postgresql with-statement


    【解决方案1】:

    您将 CTE(通用表查询)与子查询混合在一起,with 子句的美妙之处通常在于可读性:

    with initial_table as
    (
        SELECT 
        DISTINCT ctr.country_region, EXTRACT (YEAR FROM s.time_id)::int AS calendar_year, chn.channel_desc, 
        SUM(s.amount_sold) OVER (PARTITION BY ctr.country_region||chn.channel_desc||EXTRACT (YEAR FROM s.time_id)) AS amount_sold
        FROM sales s
        JOIN channels chn ON s.channel_id = chn.channel_id
        JOIN customers c ON s.cust_id  = c.cust_id
        JOIN countries ctr ON c.country_id = ctr.country_id
        WHERE ctr.country_region IN ('Americas','Asia', 'Europe')
        AND
        EXTRACT (YEAR FROM s.time_id)::int IN (1998, 1999, 2000, 2001)
        ORDER BY ctr.country_region, calendar_year, chn.channel_desc
    )
    ,second_table as
    (
        SELECT country_region, calendar_year, channel_desc, amount_sold,
        (amount_sold/SUM(amount_sold) OVER (PARTITION BY country_region||calendar_year)*100)::decimal(10,2) AS bychannels
        FROM initial_table
    )
    ,third_table as
    (
        SELECT *,
        LAG (bychannels, 4) OVER (ORDER BY 6) AS lower_salary
        FROM second_table--correct here smth wrong
    )
    ,fourth_table as
    (
        SELECT *, bychannels - lower_salary AS diff FROM third_table
    )
    SELECT country_region, calendar_year, channel_desc, 
    --'FM     999,999,999,990D'
    LPAD(to_char(amount_sold, 'FM999,999,999,990 $'),20, ' ') AS amount_sold,
    LPAD(bychannels || ' %' ,20, ' ') AS "% BY CHANNELS",
    LPAD(lower_salary || ' %    ' ,20, ' ') AS "% PREVIOUS PERIOD", 
    diff AS "% DIFF"
    FROM fourth_table WHERE calendar_year NOT IN (1998);
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-16
      • 1970-01-01
      • 2019-11-07
      • 2018-02-13
      • 2019-09-02
      • 1970-01-01
      • 2019-02-10
      相关资源
      最近更新 更多