агрегирование в подзапросах с использованием внешней ссылки внутри регистра.Ошибка получения - PullRequest
0 голосов
/ 21 февраля 2019

Это лишь малая часть моего полного запроса.

У меня есть некоторые данные, где я вычисляю значения в этом году и в прошлом году (и многое другое), используя агрегацию и подзапрос.

Нижерабочая и самая простая версия моего запроса:

SELECT distinct 
       t1.country,
       t1.manufacturer,
       t1.category,
       t1.month, 
       t1.year,
(SELECT SUM(value) FROM data  ----- value is the column name which i want to aggregate 
    WHERE mar_short_desc = t1.mar_short_desc
    AND category = t1.category
    AND manufacturer = t1.manufacturer
    AND month = t1.month
    AND year = t1.year ----- This Is the only difference Filter
) AS Company_TY, 
(SELECT SUM(value) FROM data  
    WHERE mar_short_desc = t1.mar_short_desc
    AND category = t1.category
    AND manufacturer = t1.manufacturer
    AND month = t1.month
    AND year = t1.year -1  ----- This Is the only difference Filter
) AS Company_LY,
FROM data  t1
----- Other filters are here ignored for simplicity 
) a

Я хочу оптимизировать его.Итак, попытка объединить оба подзапроса в один и использовать оператор 'case' для вычисления одинаковых значений.

Вот модифицированная версия:

SELECT distinct
       t1.country,
       t1.manufacturer,
       t1.category,
       t1.month, 
       t1.year,
(SELECT SUM(CASE WHEN year = t1.year THEN value END) AS Company_TY,
        SUM(CASE WHEN year = t1.year -1 THEN value END) AS company_LY 
FROM data
    WHERE mar_short_desc = t1.mar_short_desc
    AND category = t1.category
    AND manufacturer = t1.manufacturer
    AND month = t1.month
)
FROM data  t1
) a 

Это дает мне ОШИБКУ:«В агрегированном выражении, содержащем внешнюю ссылку, указано несколько столбцов. Если агрегируемое выражение содержит внешнюю ссылку, то эта внешняя ссылка должна быть единственным столбцом, на который есть ссылка в выражении.»

All iЯ хочу создать кадр из всех распространенных фильтров, а затем агрегировать полученный результат с помощью уникального фильтра (причина: мне не нужно фильтровать одно и то же снова и снова. Это большой код и много данных, поэтому я хочуоптимизировать)

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

В исходном примере у вас есть два столбца, которые возвращаются во внешний запрос внутренним, это может сработать, если вы откроете один из них и оставите другой в подзапросе.Я не уверен, как это будет продолжаться с тем отдельным предложением, которое вы используете.

SELECT distinct
   t1.country,
   t1.manufacturer,
   t1.category,
   t1.month, 
   t1.year,
   SUM(CASE WHEN year = t1.year THEN value END) AS Company_TY,
   (SELECT SUM(CASE WHEN year = t1.year -1 THEN value END) AS company_LY 
        FROM data
            WHERE mar_short_desc = t1.mar_short_desc
            AND category = t1.category
            AND manufacturer = t1.manufacturer
            AND month = t1.month
        )
FROM data  t1
) a 

Попробуйте также выполнить приведенный ниже запрос, он использует GROUP BY и производные таблицы, которые более эффективны.

select Data1.country
 , Data1.manufacturer
 , Data1.category
 , Data1.month
 , Data1.year
 , Data1.Total
 , Data2.Total
from (SELECT t1.country,
             t1.manufacturer,
             t1.category,
             t1.month, 
             t1.year,
             SUM(value) 'Total'
        from data
        group by t1.country,
                 t1.manufacturer,
                 t1.category,
                 t1.month, 
                 t1.year) Data1
    inner join (SELECT country,
                       manufacturer,
                       category,
                       month, 
                       year,
                       SUM(value) 'Total'
                    from data
                    group by country,
                             manufacturer,
                             category,
                             month, 
                             year) Data2 on Data2.country = Data1.country
                                        and Data2.manufacturer = Data1.manufacturer
                                        and Data2.category = Data1.category
                                        and Data2.month = Data1.month
                                        and Data2.year = Data1.year -1
0 голосов
/ 21 февраля 2019

Для оптимизации рассмотрите возможность избежать коррелированных подзапросов в SELECT и просто JOIN основной таблицы для производных таблиц.Это должно быть более эффективным, поскольку агрегация выполняется один раз, а не для каждой строки во внешнем запросе.

Ниже используются две производные таблицы из-за различий в совпадении года.Будучи более подробным с добавленными предложениями GROUP BY, он должен работать лучше, чем коррелированные подзапросы из первого блока кода SQL.Даже добавьте индексы в поля объединения для повышения производительности.

SELECT distinct
       t1.country,
       t1.manufacturer,
       t1.category,
       t1.month, 
       t1.year,
       sub1.Company_TY,
       sub2.Company_LY
FROM data  t1
INNER JOIN
   (SELECT mar_short_desc, category,  manufacturer, month, year,
           SUM(value) AS Company_TY
    FROM data 
    GROUP BY mar_short_desc, category, manufacturer, month, year
   ) sub1
ON sub1.mar_short_desc = t1.mar_short_desc
AND sub1.category = t1.category
AND sub1.manufacturer = t1.manufacturer
AND sub1.month = t1.month
AND sub1.year = t1.year

INNER JOIN
   (SELECT mar_short_desc, category,  manufacturer, month, year,
           SUM(value) AS Company_LY
    FROM data 
    GROUP BY mar_short_desc, category, manufacturer, month, year
   ) sub2
ON sub2.mar_short_desc = t1.mar_short_desc
AND sub2.category = t1.category
AND sub2.manufacturer = t1.manufacturer
AND sub2.month = t1.month
AND sub2.year = t1.year - 1
...