|
|
谜题 49 产品计件
有一张产品表:
CREATE TABLE Production
(production_center INTEGER NOT NULL, -- 生产中心
wk_date DATE NOT NULL, -- 生产日期
batch_nbr INTEGER NOT NULL, -- 批号
widget_cnt INTEGER NOT NULL, -- 本批产量
PRIMARY KEY (production_center, wk_date, batch_nbr));
老板要求把每天、每生产中心的记录均分为三组,计算每组的平均产品。
例如在 2 月 24 号, 第42号生产中心总共有21个批次,你的报表要把数据分为三组:1-7批,8-14批, 15-21批
显示每组的平均产量。
INSERT INTO Production VALUES (42,DATE '2010-2-24',1 , 110);
INSERT INTO Production VALUES (42,DATE '2010-2-24',2 , 120);
INSERT INTO Production VALUES (42,DATE '2010-2-24',3 , 130);
INSERT INTO Production VALUES (42,DATE '2010-2-24',4 , 140);
INSERT INTO Production VALUES (42,DATE '2010-2-24',5 , 150);
INSERT INTO Production VALUES (42,DATE '2010-2-24',6 , 160);
INSERT INTO Production VALUES (42,DATE '2010-2-24',7 , 170);
INSERT INTO Production VALUES (42,DATE '2010-2-24',8 , 180);
INSERT INTO Production VALUES (42,DATE '2010-2-24',9 , 190);
INSERT INTO Production VALUES (42,DATE '2010-2-24',10, 100);
INSERT INTO Production VALUES (42,DATE '2010-2-24',11, 110);
INSERT INTO Production VALUES (42,DATE '2010-2-24',12, 120);
INSERT INTO Production VALUES (42,DATE '2010-2-24',13, 130);
INSERT INTO Production VALUES (42,DATE '2010-2-24',14, 140);
INSERT INTO Production VALUES (42,DATE '2010-2-24',15, 150);
INSERT INTO Production VALUES (42,DATE '2010-2-24',16, 160);
INSERT INTO Production VALUES (42,DATE '2010-2-24',17, 170);
INSERT INTO Production VALUES (42,DATE '2010-2-24',18, 180);
INSERT INTO Production VALUES (42,DATE '2010-2-24',19, 190);
INSERT INTO Production VALUES (42,DATE '2010-2-24',20, 100);
INSERT INTO Production VALUES (42,DATE '2010-2-24',21, 110);
书中答案:
先建一个视图:
CREATE VIEW Prod3 (production_center, wk_date, widget_cnt,third)
AS SELECT v1.production_center, v1.wk_date, widget_cnt,
CASE WHEN batch_nbr <= cont/3 THEN 1
WHEN batch_nbr > (2 * cont)/3 THEN 3
ELSE 2
END
FROM Production
,(SELECT production_center,wk_date,COUNT(*) AS cont
FROM Production
GROUP BY production_center,wk_date) V1
WHERE V1.production_center = Production.production_center
AND V1.wk_date = Production.wk_date;
或者用一种更笨的方法:
CREATE VIEW Prod3 (production_center, wk_date, third, batch_nbr, widget_cnt)
AS SELECT production_center, wk_date, 1, batch_nbr,widget_cnt
FROM Production P1
WHERE batch_nbr <= (SELECT MAX(batch_nbr)/3
FROM Production P2
WHERE P1.production_center = P2.production_center
AND P1.wk_date = P2.wk_date)
UNION
SELECT production_center, wk_date, 2, batch_nbr, widget_cnt
FROM Production P1
WHERE batch_nbr > (SELECT MAX(batch_nbr)/3
FROM Production P2
WHERE P1.production_center = P2.production_center
AND P1.wk_date = P2.wk_date)
AND batch_nbr <= (SELECT 2 * MAX(batch_nbr)/3
FROM Production P2
WHERE P1.production_center = P2.production_center
AND P1.wk_date = P2.wk_date)
UNION
SELECT production_center, wk_date, 3, batch_nbr,widget_cnt
FROM Production P1
WHERE batch_nbr > (SELECT 2 * MAX(batch_nbr)/3
FROM Production P2
WHERE P1.production_center =P2.production_center
AND P1.wk_date = P2.wk_date);
然后在此视图基础上查询:
SELECT production_center, wk_date, third, COUNT(batch_nbr),
AVG(widget_cnt)
FROM Prod3
GROUP BY production_center, wk_date, third;
幸运的是咱们有一个优雅的分析函数NTILE, 解决这个问题简直不费吹灰之力:
SELECT production_center
,wk_date
,third
,AVG(widget_cnt)
FROM (SELECT p.*
,NTILE(3) OVER(PARTITION BY production_center, wk_date ORDER BY batch_nbr) AS third
FROM Production p
)
GROUP BY production_center,wk_date,third; |
|