0
 select year, 
        month ,
        d.PROD_ID, 
        T.CUSTOMER_ID,
        SUM(CASE WHEN D.OP_TYPE = 1 THEN d.qty END)    EARNED,
        SUM(CASE WHEN D.OP_TYPE = 2 THEN d.qty END)    SPEND
FROM TXN_HEADER T  , 
     TXN_DETAIL d , 
     CUSTOMER A,
     PRODUCT e 
WHERE T.AMOUNT > 0 
AND   A.TYPE  =  0
AND   T.CUSTOMER_ID = A.CUSTOMER_ID
AND   T.TXN_PK = D.TXN_PK 
and   d.PROD_ID = e.PROD_ID
and   e.unit = 0
group by year, month ,d.PROD_ID, T.CUSTOMER_ID
ORDER BY 1,2,3,4 

输出如下(此处打开和关闭不是由查询生成的,但我要求必须来自查询)

YEAR MONTH PROD CUSTOMER OPENING EARNED SPEND CLOSING 
---- ----- ---- -------- ------- ------ ----- -------
2012     8  548    12033       0      8     2       6
2012     9  509    12033       0     24     0      24
2012     9  509    12047       0     14     0      14
2012     9  548    12033       6      1     0       7
2012     9  548    12047       0      1     0       1

我需要生成上述输出。在这里,PROD_ID,CUSTOMER_ID 明智地动态地将上一个期末余额填充为期初,它应该按月计算期末余额(期初+收入支出),明智的客户,明智的产品。是否可以用 SQL 编写或需要使用 PL/SQL?

4

2 回答 2

1

我会使用分析,在分区子句中使用 PROD_ID 和 CUSTOMER_ID 以避免混淆产品和客户。

WITH
MONTHLY_BALANCE AS
(
  SELECT
    YEAR,
    MONTH,
    D.PROD_ID,
    T.CUSTOMER_ID,
    SUM(CASE WHEN D.OP_TYPE = 1 THEN D.QTY ELSE NULL END) EARNED,
    SUM(CASE WHEN D.OP_TYPE = 2 THEN D.QTY ELSE NULL END) SPEND,
  FROM TXN_HEADER T
  JOIN CUSTOMER A 
  ON    T.CUSTOMER_ID = A.CUSTOMER_ID
  JOIN TXN_DETAIL D
  ON    T.TXN_PK = D.TXN_PK
  JOIN PRODUCT E
  ON    D.PROD_ID = E.PROD_ID
  WHERE T.AMOUNT > 0
  AND   A.TYPE = 0
  AND   E.UNIT = 0
  GROUP BY YEAR, MONTH, D.PROD_ID, T.CUSTOMER_ID
)
SELECT
  YEAR,
  MONTH,
  PROD_ID,
  CUSTOMER_ID,
  SUM(NVL(EARNED, 0) - NVL(SPEND, 0)) OVER(PARTITION BY PROD_ID, CUSTOMER_ID ORDER BY YEAR, MONTH ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) OPENING,
  EARNED,
  SPEND,
  SUM(NVL(EARNED, 0) - NVL(SPEND, 0)) OVER(PARTITION BY PROD_ID, CUSTOMER_ID ORDER BY YEAR, MONTH ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT_ROW) CLOSING
FROM MONTHLY_BALANCE
ORDER BY 1, 2, 3, 4
于 2012-09-19T17:49:26.273 回答
0

CASE需要一个ELSE

CASE WHEN D.OP_TYPE = 1 THEN d.qty ELSE 0 END

如果没有 else ,当不等于和 any+ =时CASE将返回。当您不满意时,它会返回,这就是为什么您看不到这些列的任何内容。NULLD.OP_TYPE1NULLNULLWHENNULL

要计算 OPENING 和 CLOSING,您可能需要使用和之类的分析函数LEADLAG

Select year,month,prod_id,customer_id,
       LAG(closing,1,0) OVER (order by year,month,prod_id,customer_id) as opening,
       earned,spend
      ,(LAG(closing,1,0) OVER (order by year,month,prod_id,customer_id)+closing) as closing
from (WITH temp AS (select year, 
                           month ,
                           d.PROD_ID, 
                           T.CUSTOMER_ID,
                           0 OPEN,
                          SUM(CASE WHEN D.OP_TYPE = 1 THEN d.qty END)    EARNED,
                          SUM(CASE WHEN D.OP_TYPE = 2 THEN d.qty END)    SPEND,
                          0 CLOSE
                     FROM TXN_HEADER T  , 
                          TXN_DETAIL d , 
                          CUSTOMER A,
                          PRODUCT e 
                    WHERE T.AMOUNT > 0 
                      AND   A.TYPE  =  0
                      AND   T.CUSTOMER_ID = A.CUSTOMER_ID
                      AND   T.TXN_PK = D.TXN_PK 
                      and   d.PROD_ID = e.PROD_ID
                      and   e.unit = 0
                     group by year, month ,d.PROD_ID, T.CUSTOMER_ID
                     ORDER BY 1,2,3,4)
   SELECT year,month,prod_id,customer_id,open,earned,spend,(open+earned-spend) as closing
     from temp);
于 2012-09-19T14:57:35.917 回答