繁体   English   中英

使用 Oracle 的 SQL 中的分析函数将行转换为列

[英]Transforming rows into columns with Analytic functions in Oracle's SQL

我有下表

日期 价格 顾客 产品
2020 100 1 一个
2021 100 1 一个
2022 110 1 一个
2020 50 2
2021 80 2

我想转换我的数据以连续查看客户在今年(即 2022 年)和去年(即 2021 年)支付的价格,并计算其增量。 如果客户在 2022 年没有交易,我想将他们排除在我的 output 之外。

所以结果应该是这样的:

CY 价格_CY PY 价格_PY 顾客 产品 价格_Delta
2022 110 2021 100 1 一个 1.1

我想我需要自行加入并使用 window function,但不知道如何处理它?

您可以将LAG function 与CTE一起使用,如下所示:

With CTE As
(
  Select Date_ As CY, Price As Price_CY,
       Lag(Date_) Over (Partition By Customer, Product Order By Date_) As PY,
       Lag(Price) Over (Partition By Customer, Product Order By Date_) As Price_PY,
       Customer, Product,
       Price / Lag(Price) Over (Partition By Customer, Product Order By Date_) As Price_Delta
  From Your_Table
)
Select CY, Price_CY, PY, Price_PY, Customer, Product, Price_Delta
From CTE
Where CY = 2022 And Customer = 1 And Product = 'A'

查看来自uk<>fiddle的演示。

您可以将条件聚合ROW_NUMBER()分析 function 一起使用,同时将"Date"列值与过去两年的值匹配,例如

WITH  t2 AS
(
  SELECT column_value AS year, 
         MAX(CASE WHEN "Date"=column_value THEN price END) AS price, 
         Customer,Product,
         ROW_NUMBER() 
         OVER (PARTITION BY Customer,Product ORDER BY column_value DESC) AS rn 
    FROM table(sys.odcinumberlist(TO_CHAR(sysdate,'yyyy')-1,TO_CHAR(sysdate,'yyyy')))
   CROSS JOIN t
   GROUP BY column_value, Customer,Product      
)
SELECT MAX(CASE WHEN rn = 1 THEN year END) AS cy,
       MAX(CASE WHEN rn = 1 THEN price END) AS price_cy,
       MAX(CASE WHEN rn = 2 THEN year END) AS py,
       MAX(CASE WHEN rn = 2 THEN price END) AS price_py,
       Customer,Product,
       MAX(CASE WHEN rn = 1 THEN price END)/
       MAX(CASE WHEN rn = 2 THEN price END) AS price_delta
  FROM t2
 GROUP BY Customer,Product    
HAVING NVL(MAX(CASE WHEN rn = 1 THEN price END),0)*
       NVL(MAX(CASE WHEN rn = 2 THEN price END),0)>0 

演示

如果您想要相对于当前日期的当前年份和上一年(不是每个输入年份),那么您可以按两年过滤输入,然后 pivot 它:

 select cy, cy_price, py, py_price, cy_price/py_price as delta, customer_id, product from ( select * from test_tab --reduce input where dt in ( extract(year from sysdate), extract(year from sysdate) - 1 ) ) pivot( max(price) as price, max(dt) for dt in ( 2022 as cy, 2021 as py ) ) where cy is not null --there's something for this year
CY CY_PRICE PY PY_PRICE 三角洲 客户ID 产品
2022 110 2021 100 1.1 1 一个

db<> 在这里摆弄

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM