Лучшая практика при повторном использовании одного и того же запроса - PullRequest
1 голос
/ 19 июня 2019

что является альтернативой многократного использования одного и того же запроса.Я хочу сохранить запрос в каком-то месте и вызывать его всякий раз, когда мне это нужно.Я вычисляю 4 формулы: продажи MTD, продажи MTD за предыдущий год, продажи MAT, продажи MAT за предыдущий год в виде отдельных столбцов для 5 различных продуктов: A, B, C, D, E.наряду с некоторыми статическими условиями, такими как данные счета, должны быть предоставлены и прямые продажи

Я запрашиваю утверждения Case 4 (для формул) * 5 (для продуктов) раз, чтобы определить формулу со статическими условиями для всех 5 продуктов.т.е. почти 80% моего запроса повторяется 4 * 5 = 20 раз.Вместо того, чтобы повторять 80% запроса для всех 20 раз, есть ли лучший способ сделать это.Обратите внимание, мне не нужно хранить значение запроса как функцию, вместо этого я могу сохранить повторяющуюся часть запроса и вызывать ее там, где мне нужно?

Код:

SELECT A1.*,

-- MTD FOR PRODUCTS A,B,C,D

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='A'
AND
(EXTRACT (MONTH FROM DATE_MONTH)=EXTRACT(MONTH FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A))
AND 
EXTRACT (YEAR FROM DATE_MONTH)=EXTRACT(YEAR FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A)))
THEN SALES ELSE 0 END AS MTD_PRODUCT_A,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='B'
AND
(EXTRACT (MONTH FROM DATE_MONTH)=EXTRACT(MONTH FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A))
AND 
EXTRACT (YEAR FROM DATE_MONTH)=EXTRACT(YEAR FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A)))
THEN SALES ELSE 0 END AS MTD_PRODUCT_B,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='C'
AND
(EXTRACT (MONTH FROM DATE_MONTH)=EXTRACT(MONTH FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A))
AND 
EXTRACT (YEAR FROM DATE_MONTH)=EXTRACT(YEAR FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A)))
THEN SALES ELSE 0 END AS MTD_PRODUCT_C,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='D'
AND
(EXTRACT (MONTH FROM DATE_MONTH)=EXTRACT(MONTH FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A))
AND 
EXTRACT (YEAR FROM DATE_MONTH)=EXTRACT(YEAR FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A)))
THEN SALES ELSE 0 END AS MTD_PRODUCT_D,

---MTD LAST YEAR FOR PRODUCTS A,B,C,D

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='A'
AND
(EXTRACT (MONTH FROM DATE_MONTH)=EXTRACT(MONTH FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A))
AND 
EXTRACT (YEAR FROM DATE_MONTH)=(SELECT EXTRACT(YEAR FROM MAX(SHOWN_DATE))-1 FROM TABLE_A))
THEN SALES ELSE 0 END AS MTD_PY_PRODUCT_A,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='B'
AND
(EXTRACT (MONTH FROM DATE_MONTH)=EXTRACT(MONTH FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A))
AND 
EXTRACT (YEAR FROM DATE_MONTH)=(SELECT EXTRACT(YEAR FROM MAX(SHOWN_DATE))-1 FROM TABLE_A))
THEN SALES ELSE 0 END AS MTD_PY_PRODUCT_B,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='C'
AND
(EXTRACT (MONTH FROM DATE_MONTH)=EXTRACT(MONTH FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A))
AND 
EXTRACT (YEAR FROM DATE_MONTH)=(SELECT EXTRACT(YEAR FROM MAX(SHOWN_DATE))-1 FROM TABLE_A))
THEN SALES ELSE 0 END AS MTD_PY_PRODUCT_C,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='D'
AND
(EXTRACT (MONTH FROM DATE_MONTH)=EXTRACT(MONTH FROM (SELECT MAX(SHOWN_DATE) FROM TABLE_A))
AND 
EXTRACT (YEAR FROM DATE_MONTH)=(SELECT EXTRACT(YEAR FROM MAX(SHOWN_DATE))-1 FROM TABLE_A))
THEN SALES ELSE 0 END AS MTD_PY_PRODUCT_D,


----MAT SALES FOR PRODUCT A,B,C,D

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='A'
AND
(Date_Month between add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-11)
and
trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'))
THEN SALES ELSE 0 END AS MAT_PRODUCT_A,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='B'
AND
(Date_Month between add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-11)
and
trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'))
THEN SALES ELSE 0 END AS MAT_PRODUCT_B,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='C'
AND
(Date_Month between add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-11)
and
trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'))
THEN SALES ELSE 0 END AS MAT_PRODUCT_C,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='D'
AND
(Date_Month between add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-11)
and
trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'))
THEN SALES ELSE 0 END AS MAT_PRODUCT_D,


---MAT LAST YEAR SALES FOR PRODUCTS A,B,C,D

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='A'
AND
(Date_Month between add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-23)
and
add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-12))
THEN SALES ELSE 0 END AS MAT_PRODUCT_A,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='B'
AND
(Date_Month between add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-23)
and
add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-12))
THEN SALES ELSE 0 END AS MAT_PRODUCT_B,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='C'
AND
(Date_Month between add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-23)
and
add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-12))
THEN SALES ELSE 0 END AS MAT_PRODUCT_C,

CASE WHEN
ACCOUNT<> 'Not Provided' AND TYPE<> 'DIRECT' and PRODUCT='D'
AND
(Date_Month between add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-23)
and
add_months(trunc((SELECT MAX(Date_Month) AS MAX_DATE_DIST FROM TABLE_A),'month'),-12))
THEN SALES ELSE 0 END AS MAT_PRODUCT_D

FROM TABLE_A A1

Ответы [ 3 ]

1 голос
/ 19 июня 2019

Существует несколько вариантов.

Если базовые данные нужно создавать только периодически - скажем, один раз в день или один раз в неделю, тогда вы можете запланировать работу и создать таблицу.Это, вероятно, наиболее распространенное решение для разных баз данных для сложных запросов.

Если сам запрос не является особенно сложным или если вам необходимо обновлять данные каждый раз, тогда используйте (обычное) представление.Это встроенная функция для инкапсуляции запросов.

Другой альтернативой является материализованное представление.Это как таблицы, в которых данные не должны (явно) пересчитываться.Это как представления, в которых данные обновляются.Подробнее о них вы можете узнать из документации .

0 голосов
/ 19 июня 2019

Используйте аналитическую функцию, чтобы найти максимальное значение даты:

SELECT A1.*,
       CASE
         WHEN ACCOUNT<> 'Not Provided'
         AND  TYPE<> 'DIRECT'
         AND  PRODUCT='A'
         AND  date_month_trunc = max_date_month
         THEN SALES
         ELSE 0
       END AS MTD_PRODUCT_A,
       /* B, C, D */
       CASE
         WHEN ACCOUNT <> 'Not Provided'
         AND  TYPE<> 'DIRECT'
         AND  PRODUCT='A'
         AND  date_month_trunc = max_date_month - INTERVAL '1' YEAR
         THEN SALES
         ELSE 0
       END AS MTD_PY_PRODUCT_A,
       /* B, C, D */
       CASE
         WHEN ACCOUNT<> 'Not Provided'
         AND  TYPE<> 'DIRECT'
         AND  PRODUCT='A'
         AND  date_month BETWEEN ADD_MONTHS( max_date_month - 11 ) AND max_date_month
         THEN SALES
         ELSE 0
       END AS MAT_PRODUCT_A,
       /* B, C, D */
       CASE
         WHEN ACCOUNT<> 'Not Provided'
         AND  TYPE<> 'DIRECT'
         AND  PRODUCT='A'
         AND  date_month BETWEEN ADD_MONTHS( max_date_month, -23 ) AND ADD_MONTHS( max_date_month, -12 )
         THEN SALES
         ELSE 0
       END AS MAT_PRODUCT_A
       /* B, C, D */
FROM (
  SELECT a.*,
         TRUNC( date_month, 'MM' ) AS date_month_trunc,
         MAX( TRUNC( date_month, 'MM' ) ) OVER () AS max_date_month
  FROM   TABLE_A a
) A1

Вы можете сделать его еще короче, переместив общие элементы CASE в подзапрос:

SELECT A1.*,
       CASE
         WHEN PRODUCT='A'
         AND  date_month_trunc = max_date_month
         THEN not_provided_direct_sales
         ELSE 0
       END AS MTD_PRODUCT_A,
       /* B, C, D */
       CASE
         WHEN PRODUCT='A'
         AND  date_month_trunc = max_date_month - INTERVAL '1' YEAR
         THEN not_provided_direct_sales
         ELSE 0
       END AS MTD_PY_PRODUCT_A,
       /* B, C, D */
       CASE
         WHEN PRODUCT='A'
         AND  date_month BETWEEN ADD_MONTHS( max_date_month - 11 ) AND max_date_month
         THEN not_provided_direct_sales
         ELSE 0
       END AS MAT_PRODUCT_A,
       /* B, C, D */
       CASE
         WHEN PRODUCT='A'
         AND  date_month BETWEEN ADD_MONTHS( max_date_month, -23 ) AND ADD_MONTHS( max_date_month, -12 )
         THEN not_provided_direct_sales
         ELSE 0
       END AS MAT_PRODUCT_A
       /* B, C, D */
FROM (
  SELECT a.*,
         CASE
           WHEN ACCOUNT<> 'Not Provided'
           AND  TYPE<> 'DIRECT'
           THEN SALES
           ELSE 0
         END AS not_provided_direct_sales,
         TRUNC( date_month, 'MM' ) AS date_month_trunc,
         MAX( TRUNC( date_month, 'MM' ) ) OVER () AS max_date_month
  FROM   TABLE_A a
) A1
0 голосов
/ 19 июня 2019

Вы можете создать временную таблицу, а затем вызвать хранимую процедуру для заполнения временной таблицы, используя ключевое слово exec

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...