SQL Lite中具有多个条件和列的AVG函数
我知道如何在条件下实现avg功能,但无法满足我的具体需求。 假设我正在使用一个名为sales_performance的表SQL Lite中具有多个条件和列的AVG函数,sql,sqlite,conditional,average,Sql,Sqlite,Conditional,Average,我知道如何在条件下实现avg功能,但无法满足我的具体需求。 假设我正在使用一个名为sales_performance的表 product_ID sales_period sales_qty sales_index product_sub goal_met C12 0001 15 20 D71 Y D71 0001 07
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\u index
在Goal\u Met='Y'
时的sales\u index
平均值以及其子产品的sales\u index
在Goal\u Met='N'
时的平均值
因此,例如,如果我想计算产品'C12'
在sales\u期间
0003
的销售指数目标,它将被计算为:
(30
,20
,15
)的平均值,其中30
和20
是销售期1
和2
中产品'C12'
的销售指数,而15
是销售期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的销售指数目标,但不适用于产品F20(更详细的原因请参见我在答案下面的评论)
您可以看到产品F20的查询结果,使用窗口函数是一个很好的开始。一个问题在于,您想要平均来自不同列的值,并且可能有不同的发生次数
我认为你需要把计算分解来计算平均值:求和这些值,然后除以发生次数之和
考虑:
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'
在中,使用示例数据返回:
| 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 |
不确定这是否真的需要窗口函数
下面的示例只是通过C12产品自链接表和组
选择c12.*,子销售索引
来自销售业绩c12
左连接销售和绩效分接头
子销售周期
产品标识|销售|期间|销售|数量|销售|指数|产品|子|目标|达成|销售|指数
:--------- | :----------- | :-------- | :---------- | :---------- | :------- | :----------
C12 | 0001 | 15 | 20 | D71 | Y |空
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
选择
c12*
,四舍五入(平均值(次级销售指数),1)作为销售指数目标
来自销售业绩c12
左连接销售和绩效分接头
子销售周期
产品标识|销售|期间|销售|数量|销售|指数|产品|子|目标|达成|销售|指数|目标
:--------- | :----------- | :-------- | :---------- | :---------- | :------- | :---------------
C12 | 0001 | 15 | 20 | D71 | Y |空
C12 | 0002 | 15 | 30 | C05 | Y | 17.5
C12 | 0003 | 05 | 04 | F20 | N | 21.7
dbfiddle嗨,谢谢你的回答。这主要起作用,但有一个问题。假设我试图计算销售周期0003中F20而不是C12的销售指数目标值。返回值应为30,因为只出现一次a(F20和Y)或(C12和N)。但是,对于C12和N,代码不返回0,而是在C12的目标满足=Y的情况下返回C12产品的销售指数。因此,它返回周期0001的D71和周期0002的C05的销售指数。知道为什么会这样吗?事实上,第二种情况下C12的销售指数目标应该是17.5,而不是20,我不知道它是否在计算周期0001内产品C05的销售指数。您好,感谢您花时间回答,但除销售周期0003外的值不是我要查找的值。第一个周期的值应为空,第二个周期的值应为17.5case@memokerobi只需更改
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