有没有办法在postgresql中后面的CTE中引用前面的CTE

问题描述 投票:0回答:1

在 PostgreSQL 中工作,我打算使用 CTE 的输出作为参考来加入其下面的另一个 CTE。

我在 SQLServer 和 Synapse 中无数次使用了这种风格,但是我发现很难在 PostgreSQL 中复制。

WITH RECURSIVE CTE_mst_rv_prod AS (
    --CTE to answer the product with highest review
        SELECT product_id, COUNT(review) "total_reviews", 
        RANK() OVER(ORDER BY COUNT(review) DESC) "Rank"
        FROM public.reviews
        GROUP BY product_id
        ORDER BY RANK() OVER(ORDER BY COUNT(review) DESC)
        LIMIT 1
    ),
    CTE_pd_or_dt AS (
    --CTE to answer the day product was ordered the most
        SELECT P.product_id, O.order_date "MOST_ORDERED_DAY", COUNT(order_id) AS "COUNT_OF_ORDERS"
        FROM CTE_mst_rv_prod P
        JOIN public.orders O ON P.product_id = O.product_id
        GROUP BY P.product_id, O.order_date
        ORDER BY COUNT(order_id) DESC
        LIMIT 1
    ),
    CTE_or_dt AS(--here's the CTE that's unable to use column from the CTE above it
    --CTE to answer if d day with highest order is a public holiday or not
        SELECT D.calendar_dt AS "MOST_ORDERED_DAY",
            CASE 
                WHEN D.day_of_the_week_num IN (1,5) AND working_day = false THEN TRUE
                ELSE FALSE
            END is_public_holiday
        FROM CTE_pd_or_dt 
        INNER JOIN public.dim_dates D ON
        CTE_pd_or_dt.MOST_ORDERED_DAY = D.calendar_dt
    ),
    --CTE to answer the timeliness problem
    CTE_shp_cond AS(
    SELECT O.order_date, O.product_id, S.shipment_date, S.delivery_date,
        O.order_id, CASE WHEN S.shipment_date - O.order_date >= 6 AND
        delivery_date ISNULL THEN 'late' ELSE 'early'
        END "shipment_condition"
    FROM public.orders O
    JOIN public.shipments_deliveries S ON S.order_id = O.order_id
    JOIN CTE_mst_rv_prod RV ON O.product_id = RV.product_id
    )
    
SELECT A.product_id, B.MOST_ORDERED_DAY, C.is_public_holiday, A.total_reviews,

    (SELECT ROUND((COUNT(*) * 100.00)/ top_product.total_reviews, 4)
     FROM public.reviews AS r2 
     JOIN CTE_mst_rv_prod "mrp" ON mrp.product_id = r2.product_id
     WHERE r2.review = 1) AS "pct_one_star_review",
     
     (SELECT ROUND((COUNT(*) * 100.00)/ top_product.total_reviews, 4)
     FROM public.reviews AS r2
     JOIN CTE_mst_rv_prod "mrp" ON mrp.product_id = r2.product_id
     WHERE r2.review = 2)   AS pct_two_star_review,
     
     (SELECT ROUND((COUNT(*) * 100.00)/ top_product.total_reviews, 4)
     FROM public.reviews AS r2
     JOIN CTE_mst_rv_prod "mrp" ON mrp.product_id = r2.product_id
     WHERE r2.review = 3)   AS pct_three_star_review,
     
     (SELECT ROUND((COUNT(*) * 100.00)/ top_product.total_reviews, 4)
     FROM public.reviews AS r2
     JOIN CTE_mst_rv_prod "mrp" ON mrp.product_id = r2.product_id
     WHERE r2.review = 4)   AS pct_four_star_review,
     
     (SELECT ROUND((COUNT(*) * 100.00)/ top_product.total_reviews, 4)
     FROM public.reviews AS r2
     JOIN CTE_mst_rv_prod "mrp" ON mrp.product_id = r2.product_id
     WHERE r2.review = 5)   AS pct_five_star_review

FROM CTE_mst_rv_prod A
LEFT JOIN CTE_pd_or_dt B ON A.product_id = B.product_id
LEFT JOIN CTE_or_dt C ON C.order_date = B.MOST_ORDERED_DAY

这是我的错误消息: 错误:列 cte_pd_or_dt.most_ordered_day 不存在 第 28 行:CTE_pd_or_dt.MOST_ORDERED_DAY = D.calendar_dt ^

SQL状态:42703 性格:950

我在 PostgreSQLL 工作,这是一个真正的压力。

sql postgresql common-table-expression psql
1个回答
0
投票

我已经能够修复它,问题是因为在 postgresql 中,CTE 别名仅在该主块中可用,因此当我根据初始列名进行连接时,错误消失并且连接工作。

© www.soinside.com 2019 - 2024. All rights reserved.