我需要计算过去三年中某个项目的价格变化(包括成本和变化百分比)。
该表有四个字段:
SKU_no, Date_updated, Price, Active_flag
当Active_flag
字段为A
时,该项处于有效状态,而I
处于非活动状态时。有些项目的年份没有改变价格,所以他们没有三年的非活动旗帜参赛作品。
样本表
SKU_NO Update_date Price Active_flag
30 1/1/1999 40.8 I
33 1/1/2014 70.59 A
33 1/1/2013 67.23 I
33 1/1/2012 60.03 I
33 1/1/2011 55.08 I
33 1/1/2010 55.08 I
34 1/1/2009 51 A
36 1/1/2014 70.59 A
36 1/1/2013 67.23 I
36 1/1/2012 60.03 I
38 1/1/2002 43.32 A
38 1/1/2001 43.32 I
38 4/8/2000 43.32 I
38 1/1/1999 43.32 I
39 1/1/2014 73.08 A
39 1/1/2013 69.6 I
39 1/1/2012 62.13 I
39 1/1/2011 57 I
39 1/1/2010 57 I
39 1/1/2009 52.8 I
这是我写的第一个查询。我不太熟悉复杂的计算
select
s.VENDOR,
s.FISCAL_YEAR,
s.FISCAL_MONTH_NO,
s.FISCAL_YEAR||'_'||FISCAL_MONTH_NO as PERIOD,
CASE WHEN S.COST_USED_FLAG IN ('CONTRACT') THEN 'CONTRACT' ELSE 'NON-CONTRACT' END AS CONTRACT_TYPE,
CASE WHEN ((s.FISCAL_YEAR = 2014 AND FISCAL_MONTH_NO <=9) OR (FISCAL_YEAR = 2013 AND FISCAL_MONTH_NO >=10)) THEN 'CP_1'
WHEN ((s.FISCAL_YEAR = 2013 AND FISCAL_MONTH_NO <= 9) OR (FISCAL_YEAR = 2012 AND FISCAL_MONTH_NO >=10)) THEN 'CP_2'
WHEN ((s.FISCAL_YEAR = 2012 AND FISCAL_MONTH_NO <= 9) OR (FISCAL_YEAR = 2011 AND FISCAL_MONTH_NO >=10)) THEN 'CP_3'
ELSE 'NULL' END CAGR_PERIODS,
CASE WHEN s.MARKET IN ('PO', 'SC', 'OC') THEN 'PC' ELSE 'EC' END AS MARKET_TYPE,
s.MARKET,
s.COST_PLUS_FLAG,
s.COST_USED_FLAG,
LPAD(S.PC_ITEM_NO,6,'0') AS NEW_ITEM_NO,
s.PC_ITEM_NO,
i.ITEM_NO,
i.VEND_CAT_NUM,
i.DESCRIPTION,
s.PC_PROD_CAT,
s.PC_PROD_SUBCAT,
i.SELL_UOM,
i.QTY_PER_SELL_UOM,
i.PRIMARY_UOM,
i.HEAD_CONV_FACT,
SUM(s.QTY_EACH) AS QUANTITY_SOLD,
SUM(s.EXT_GROSS_COGS) AS TOTAL_COGS,
SUM(s.EXT_GROSS_COGS)/ SUM(s.QTY_EACH) as NET_SALES,
SUM(s.EXT_SALES)/ SUM(s.QTY_EACH) as ASP,
SUM(s.EXT_SALES) AS TOTAL_SALES,
SUM(S.EXT_SALES) - SUM(S.EXT_GROSS_COGS) as GROSS_PROFIT
from SIXSIGMA.CIA_ALL_SALES_TREND_DATA s
INNER JOIN MGMSH.ITEM i
ON S.PC_ITEM_NO = I.ITEM_NO
WHERE S.VENDOR = 'BD' AND
(S.EXT_SALES IS NOT NULL AND S.FISCAL_YEAR IN ('2013','2012','2011'))
GROUP BY
s.VENDOR,
s.FISCAL_YEAR,
s.FISCAL_MONTH_NO,
s.FISCAL_YEAR||'_'||FISCAL_MONTH_NO,
CASE WHEN s.MARKET IN ('PO', 'SC', 'OC') THEN 'PC' ELSE 'EC' END,
CASE WHEN S.COST_USED_FLAG IN ('CONTRACT') THEN 'CONTRACT' ELSE 'NON-CONTRACT' END,
CASE WHEN ((s.FISCAL_YEAR = 2014 AND FISCAL_MONTH_NO <=9) OR (FISCAL_YEAR = 2013 AND FISCAL_MONTH_NO >=10)) THEN 'CP_1'
WHEN ((s.FISCAL_YEAR = 2013 AND FISCAL_MONTH_NO <= 9) OR (FISCAL_YEAR = 2012 AND FISCAL_MONTH_NO >=10)) THEN 'CP_2'
WHEN ((s.FISCAL_YEAR = 2012 AND FISCAL_MONTH_NO <= 9) OR (FISCAL_YEAR = 2011 AND FISCAL_MONTH_NO >=10)) THEN 'CP_3'
ELSE 'NULL' END,
s.MARKET,
s.COST_USED_FLAG,
s.COST_PLUS_FLAG,
s.PC_ITEM_NO,
s.PC_PROD_CAT,
i.SELL_UOM,
i.QTY_PER_SELL_UOM,
i.PRIMARY_UOM,
i.HEAD_CONV_FACT,
i.DESCRIPTION,
i.VEND_CAT_NUM,
s.PC_PROD_SUBCAT,
i.ITEM_NO
ORDER BY s.PC_ITEM_NO,s.FISCAL_YEAR, s.FISCAL_MONTH_NO
答案 0 :(得分:0)
有几种方法可以解决这个问题,但我建议使用窗口函数,例如LAG
或LEAD
。使用这些函数,您可以引用相邻的行。例如:
lead(column, offset, default) over (partition by some_column order by column)
在下面的示例中:
lead(price, 1, price) over (partition by sku_no order by update_date desc)
以下是一个包含示例数据的工作示例:
with sample_data as (
select '30' sku_no, to_date('1/1/1999','DD/MM/YYYY') update_date, 40.8 price, 'I' active_flag from dual union all
select '33', to_date('1/1/2014','DD/MM/YYYY'), 70.59, 'A' from dual union all
select '33', to_date('1/1/2013','DD/MM/YYYY'), 67.23, 'I' from dual union all
select '33', to_date('1/1/2012','DD/MM/YYYY'), 60.03, 'I' from dual union all
select '33', to_date('1/1/2011','DD/MM/YYYY'), 55.08, 'I' from dual union all
select '33', to_date('1/1/2010','DD/MM/YYYY'), 55.08, 'I' from dual union all
select '34', to_date('1/1/2009','DD/MM/YYYY'), 51 , 'A' from dual union all
select '36', to_date('1/1/2014','DD/MM/YYYY'), 70.59, 'A' from dual union all
select '36', to_date('1/1/2013','DD/MM/YYYY'), 67.23, 'I' from dual union all
select '36', to_date('1/1/2012','DD/MM/YYYY'), 60.03, 'I' from dual union all
select '38', to_date('1/1/2002','DD/MM/YYYY'), 43.32, 'A' from dual union all
select '38', to_date('1/1/2001','DD/MM/YYYY'), 43.32, 'I' from dual union all
select '38', to_date('4/8/2000','DD/MM/YYYY'), 43.32, 'I' from dual union all
select '38', to_date('1/1/1999','DD/MM/YYYY'), 43.32, 'I' from dual union all
select '39', to_date('1/1/2014','DD/MM/YYYY'), 73.08, 'A' from dual union all
select '39', to_date('1/1/2013','DD/MM/YYYY'), 69.6 , 'I' from dual union all
select '39', to_date('1/1/2012','DD/MM/YYYY'), 62.13, 'I' from dual union all
select '39', to_date('1/1/2011','DD/MM/YYYY'), 57 , 'I' from dual union all
select '39', to_date('1/1/2010','DD/MM/YYYY'), 57 , 'I' from dual union all
select '39', to_date('1/1/2009','DD/MM/YYYY'), 52.8 , 'I' from dual)
select
sku_no,
update_date,
price,
lead(price,1, price) over (partition by sku_no order by update_date desc) prior_price, -- Showing the offset
price - lead(price,1, price) over (partition by sku_no order by update_date desc) price_difference, -- Calculate the difference
round((price - lead(price,1, price) over (partition by sku_no order by update_date desc)) * 100 /price, 2) percent_change -- Calculate the percentage
from sample_data
where update_date >= add_months(trunc(sysdate,'YYYY'),-36); -- You said in the last three years
您还可以按排序使用不同排序的LAG
。如果您想计算三年前的差异,我建议使用KEEP
函数。