是否有一种无需使用“ JOINS”和“ WITH AS”方法即可获得相同输出的方法

时间:2019-10-04 21:03:06

标签: sql oracle aggregate-functions

我有一个如此漫长的查询,每年,每个月和每个星期都按品牌给我平均分组。这可以正常工作,但是我想知道是否有更好的方法来做到这一点并保存一些代码行,时间太长了。 我使用多个“ With as”,因为我需要按周,月,年显示平均值。 我需要由三元组id_item ||组成的元素的平均价格。 name_item ||价格> = 1的品牌。

WITH 
YEAR_2018 AS(
SELECT BRAND, AVG(PRICE)AVG_2018, 0 AS AVG_2019, 0 AS JAN, 0 AS FEB...
FROM
(SELECT ID_ITEM || NAME_ITEM || BRAND, SUM(PRICE), BRAND, 
FROM MY TABLE
WHERE EXTRACT (YEAR FROM DATE) = 2018
GROUP BY ID_ITEM || NAME_ITEM || BRAND, BRAND)
GROUP BY BRAND)

YEAR_2019 AS(
SELECT BRAND, 0 AS AVG_2018, AVG(PRICE)AVG_2019, 0 AS JAN, 0 AS FEB...
FROM
(SELECT ID_ITEM || NAME_ITEM || BRAND, SUM(PRICE), BRAND, 
FROM MY TABLE
WHERE EXTRACT (YEAR FROM DATE) = 2019
GROUP BY ID_ITEM || NAME_ITEM || BRAND, BRAND)
GROUP BY BRAND)

JAN_2019 AS(...)
...

SELECT YEAR_2018.BRAND, YEAR_2018 .AVG_2018, YEAR_2019.AVG_2019 ...
FROM YEAR_2018 LEFT JOIN YEAR_2019 ON YEAR_2018.BRAND = YEAR_2019.BRAND
LEFT JOIN JAN_2019 ON JAN_2019.BRAND = YEAR_2018.BRAND ...
BRAND  |   AVG_2018  |  AVG_2019  |  AVG_JAN  |  AVG_FEB | ...
==============
X            13.2        ...
-----------------
Y            25.6        ...
-----------------

1 个答案:

答案 0 :(得分:1)

通过使用条件聚合,您可以获得单个结果相同的结果:

SELECT 
    brand, 
    AVG(CASE WHEN EXTRACT(YEAR FROM my_date) = 2018 THEN price END) AVG_2018,
    AVG(CASE WHEN EXTRACT(YEAR FROM my_date) = 2019 THEN price END) AVG_2019,
    AVG(CASE WHEN TRUNC(my_date, 'mm') = TO_DATE('2018-01', 'yyyy-mm' THEN price END) THEN AVG_JAN_2018,
    AVG(CASE WHEN TRUNC(my_date, 'mm') = TO_DATE('2018-02', 'yyyy-mm' THEN price END) THEN AVG_FEB_2018,
    ....
FROM my_table
GROUP BY brand
WHERE EXTRACT(YEAR FROM my_date) IN (2018, 2019)

该技术利用AVG()忽略NULL值的事实。