重复使用相同查询的最佳做法

时间:2019-06-19 10:16:19

标签: sql oracle

什么是多次重复使用同一查询的替代方法。我想将查询存储在某个地方,并在需要时调用它。 我正在计算4个公式:MTD销售量,MTD上一年的销售量,MAT的销售量,MAT的上一年的销售量,分别作为5种不同产品的列:A,B,C,D,E。以及一些静态条件(例如帐户详细信息和直接销售),应该提供

我要查询Case语句4次(对于公式)* 5次(对于产品),以为所有5个产品定义具有静态条件的公式。即我的查询中几乎有80%重复了4 * 5 = 20次。没有比这20次重复80%的查询的方法了,还有什么更好的办法了。请注意,我不必将查询的值存储为函数,而是可以存储查询的重复部分并在需要的地方调用它?

代码:

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 个答案:

答案 0 :(得分:1)

有几种选择。

如果仅需要定期创建基础数据(例如,每天一次或每周一次),则可以安排作业并创建表。这可能是跨不同数据库处理复杂查询的最常见解决方案。

如果查询本身不是特别复杂,或者每次都需要最新数据,则使用(常规)视图。这是封装查询的内置功能。<​​/ p>

另一个选择是实例化视图。这些就像表一样,因为不需要(显式)重新计算数据。这些就像视图一样,因为数据是最新的。您可以在documentation中进一步了解它们。

答案 1 :(得分:0)

使用分析函数查找最大日期值:

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

答案 2 :(得分:-1)

您可以创建一个临时表,然后使用exec关键字

调用存储过程以填充临时表。