我想出了如何用条件/ s做avg函数,但我不能让它适合我的特定需要。假设我正在使用名为sales_performance的表
product_ID sales_period sales_qty sales_index product_sub goal_met
C12 0001 15 20 D71 Y
D71 0001 07 09 C12 N
F20 0001 25 30 C05 Y
C05 0001 10 15 F20 N
C12 0002 15 30 C05 Y
C05 0002 12 06 C12 N
D71 0002 30 20 F20 Y
F20 0002 20 15 D71 N
C12 0003 05 04 F20 N
F20 0003 40 35 C12 Y
D71 0003 20 20 C05 Y
C05 0003 12 10 D71 N
我想为产品C12计算一个名为sales_index_goal的新值。然后,该值的公式为:
sales_index
产品'C12'
的平均值Goal_Met = 'Y'
和sales_index
的sub_product
当Goal_Met = 'N'
在那之前的销售期间。
因此,例如,如果我想为'C12'
sales_period
计算产品0003
的sales_index_goal,则计算如下:
平均值(
30
,20
,15
)其中30
和20
是产品sales_index
的'C12'
es在销售期1
和2
和15
是产品sales_index
在销售期'F20'
的2
。
我在确切的销售期间计算这个值没有任何问题。但是,我很难想出一个查询,为所有销售期计算产品'C12'
的这个值。目前,我写的这个查询不起作用:
SELECT
s.*,
AVG(CASE
WHEN s2.goal_met = "Y" AND s2.product_id = "C2"
THEN s2.sales_index
WHEN s2.product_id = (
SELECT s2.product_sub WHERE s2.product_id = "C12"
) AND s2.goals_met = "N"
THEN s2.sales_index
ELSE NULL
END)
OVER (
ORDER BY s.sales_period
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
) AS sales_index_goal
FROM
sales_performance s,
sales_performance s2
WHERE s.product_id = "C12"
我真的很感激任何帮助。额外奖励:计算所有销售期间所有产品的此值。
编辑:以下答案适用于计算产品C12的sales_index_goal但是,它不适用于产品F20(更详细的原因,为什么它不起作用是在我的评论下面的答案)你可以看到查询的结果产品F20 here
不确定这实际上需要窗口功能。
以下示例仅通过C12产品自行链接表和组。
CREATE TABLE sales_performance ( product_ID varchar(3) not null, sales_period varchar(4) not null, sales_qty char(2) not null, sales_index char(2) not null, product_sub char(3) not null, goal_met char(1) not null, PRIMARY KEY (product_ID, sales_period) )
INSERT INTO sales_performance (product_ID,sales_period,sales_qty,sales_index,product_sub,goal_met) VALUES ('C12','0001','15','20','D71','Y') ,('D71','0001','07','09','C12','N') ,('F20','0001','25','30','C05','Y') ,('C05','0001','10','15','F20','N') ,('C12','0002','15','30','C05','Y') ,('C05','0002','12','06','C12','N') ,('D71','0002','30','20','F20','Y') ,('F20','0002','20','15','D71','N') ,('C12','0003','05','04','F20','N') ,('F20','0003','40','35','C12','Y') ,('D71','0003','20','20','C05','Y') ,('C05','0003','12','10','D71','N') ;
SELECT c12.*, sub.sales_index FROM sales_performance c12 LEFT JOIN sales_performance sub ON sub.sales_period < c12.sales_period AND ( (sub.product_ID = c12.product_sub AND sub.goal_met = 'N') OR (sub.product_ID = c12.product_ID AND sub.goal_met = 'Y') ) WHERE c12.product_id = 'C12' ORDER BY c12.product_ID, c12.sales_period, sub.product_ID
product_ID | sales_period | sales_qty | sales_index | product_sub | goal_met | sales_index :--------- | :----------- | :-------- | :---------- | :---------- | :------- | :---------- C12 | 0001 | 15 | 20 | D71 | Y | null C12 | 0002 | 15 | 30 | C05 | Y | 15 C12 | 0002 | 15 | 30 | C05 | Y | 20 C12 | 0003 | 05 | 04 | F20 | N | 20 C12 | 0003 | 05 | 04 | F20 | N | 30 C12 | 0003 | 05 | 04 | F20 | N | 15
SELECT c12.* , ROUND(AVG(sub.sales_index),1) AS sales_index_goal FROM sales_performance c12 LEFT JOIN sales_performance sub ON sub.sales_period < c12.sales_period AND ( (sub.product_ID = c12.product_sub AND sub.goal_met = 'N') OR (sub.product_ID = c12.product_ID AND sub.goal_met = 'Y') ) WHERE c12.product_id = 'C12' GROUP BY c12.product_ID, c12.sales_period ORDER BY c12.product_ID, c12.sales_period;
product_ID | sales_period | sales_qty | sales_index | product_sub | goal_met | sales_index_goal :--------- | :----------- | :-------- | :---------- | :---------- | :------- | :--------------- C12 | 0001 | 15 | 20 | D71 | Y | null C12 | 0002 | 15 | 30 | C05 | Y | 17.5 C12 | 0003 | 05 | 04 | F20 | N | 21.7
db <>小提琴here
使用窗口功能是一个很好的起点。一个问题在于,您希望平均来自不同列的值,并且可能具有不同的出现次数。
我认为你需要打破计算以计算平均值:将值相加,然后将其除以出现的总和。
考虑:
SELECT *
FROM (
SELECT
s.*,
(
0.0 +
COALESCE(SUM(CASE WHEN goal_met = 'Y' THEN sales_index END) OVER(
PARTITION BY product_id
ORDER BY sales_period
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
), 0)
+ COALESCE(SUM(CASE WHEN goal_met = 'N' THEN sales_index END) OVER(
PARTITION BY product_sub
ORDER BY sales_period
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
), 0)
) / (
COALESCE(SUM(goal_met = 'Y') OVER(
PARTITION BY product_id
ORDER BY sales_period
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
), 0)
+ COALESCE(SUM(goal_met = 'N') OVER(
PARTITION BY product_sub
ORDER BY sales_period
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
), 0)
) AS sales_index_goal
FROM sales_performance s
) x WHERE product_ID = 'C12'
在this DB fiddle中,使用您的示例数据,返回:
| product_ID | sales_period | sales_qty | sales_index | product_sub | goal_met | sales_index_goal |
| ---------- | ------------ | --------- | ----------- | ----------- | -------- | ------------------ |
| C12 | 1 | 15 | 20 | D71 | Y | |
| C12 | 2 | 15 | 30 | C05 | Y | 20 |
| C12 | 3 | 5 | 4 | F20 | N | 21.666666666666668 |