Sql 在Oracle汇总中组合MAX和SUM
以下是我的SQL:Sql 在Oracle汇总中组合MAX和SUM,sql,oracle,oracle12c,Sql,Oracle,Oracle12c,以下是我的SQL: WITH source1 AS ( SELECT 'Fruit' foodtype, 'Apple' food, 20 weight FROM dual UNION SELECT 'Fruit' foodtype, 'Apple' food, 30 weight FROM dual UNION SELECT 'Fruit' foodtype, 'Grape' food, 1 weight FROM dual UNION SELECT 'Veg'
WITH source1 AS (
SELECT 'Fruit' foodtype, 'Apple' food, 20 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Apple' food, 30 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Grape' food, 1 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Carrot' food, 40 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Leek' food, 20 weight FROM dual
)
SELECT grouping(food) lv, foodtype, food, max(weight) weight
FROM source1
GROUP BY foodtype, ROLLUP (food);
输出如下所示:
LV FOODTYPE FOOD WEIGHT
-- -------- ------ ------
0 Veg Leek 20
0 Veg Carrot 40
1 Veg 40
0 Fruit Apple 30
0 Fruit Grape 1
1 Fruit 30
LV FOODTYPE FOOD WEIGHT
-- -------- ------ ------
0 Veg Leek 20
0 Veg Carrot 40
1 Veg 60
0 Fruit Apple 30
0 Fruit Grape 1
1 Fruit 31
WITH source1 AS (
SELECT 'Fruit' foodtype, 'Apple' food, 20 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Apple' food, 30 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Grape' food, 1 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Carrot' food, 40 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Leek' food, 20 weight FROM dual
)
SELECT grouping(s.food) lv, s.foodtype, s.food,
CASE WHEN grouping(s.food)=1 THEN
sum(CASE WHEN grouping(s.food)=1 THEN 0 ELSE max(s.weight) END) OVER (PARTITION BY s.foodtype ORDER BY s.food)
ELSE
max(s.weight)
END weight
FROM source1 s
GROUP BY s.foodtype, ROLLUP (s.food)
我希望它看起来像这样:
LV FOODTYPE FOOD WEIGHT
-- -------- ------ ------
0 Veg Leek 20
0 Veg Carrot 40
1 Veg 40
0 Fruit Apple 30
0 Fruit Grape 1
1 Fruit 30
LV FOODTYPE FOOD WEIGHT
-- -------- ------ ------
0 Veg Leek 20
0 Veg Carrot 40
1 Veg 60
0 Fruit Apple 30
0 Fruit Grape 1
1 Fruit 31
WITH source1 AS (
SELECT 'Fruit' foodtype, 'Apple' food, 20 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Apple' food, 30 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Grape' food, 1 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Carrot' food, 40 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Leek' food, 20 weight FROM dual
)
SELECT grouping(s.food) lv, s.foodtype, s.food,
CASE WHEN grouping(s.food)=1 THEN
sum(CASE WHEN grouping(s.food)=1 THEN 0 ELSE max(s.weight) END) OVER (PARTITION BY s.foodtype ORDER BY s.food)
ELSE
max(s.weight)
END weight
FROM source1 s
GROUP BY s.foodtype, ROLLUP (s.food)
换言之,我希望汇总结果是每种食物的最大重量的总和,而不是食物种类中所有最大重量的总和
我确实有一种解决方案,但这意味着必须添加一层额外的SQL语句嵌套:
WITH source1 AS (
SELECT 'Fruit' foodtype, 'Apple' food, 20 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Apple' food, 30 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Grape' food, 1 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Carrot' food, 40 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Leek' food, 20 weight FROM dual
), source_grp AS (
SELECT s.foodtype, s.food, max(s.weight) max_weight
FROM source1 s
GROUP BY foodtype, food
)
SELECT grouping(g.food) lv, g.foodtype, g.food, sum(g.max_weight) weight
FROM source_grp g
GROUP BY g.foodtype, ROLLUP (g.food);
有没有一种不需要额外嵌套的方法
当然,这个例子与我的实际情况相比大大简化了,这就是为什么我试图找到一种减少代码行数的方法。将SQL语句减少60行代码可以大大简化其长期维护。您可以使用row\u number代替:
您可以将window函数与CASE Expression结合使用,以获得所需的结果: 您可以使用Union,因此总选择数仅为2
WITH source1 AS (
SELECT 'Fruit' foodtype, 'Apple' food, 20 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Apple' food, 30 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Grape' food, 1 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Carrot' food, 40 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Leek' food, 20 weight FROM dual
)
SELECT foodtype, food, max(weight) weight
FROM source1
GROUP BY foodtype, food
UNION
(SELECT DISTINCT FOODTYPE, NULL, SUM(WEIGHT) TOTAL_WEIGHT FROM SOURCE1 GROUP BY FOODTYPE);
几天后再次访问此。可以这样做:
LV FOODTYPE FOOD WEIGHT
-- -------- ------ ------
0 Veg Leek 20
0 Veg Carrot 40
1 Veg 40
0 Fruit Apple 30
0 Fruit Grape 1
1 Fruit 30
LV FOODTYPE FOOD WEIGHT
-- -------- ------ ------
0 Veg Leek 20
0 Veg Carrot 40
1 Veg 60
0 Fruit Apple 30
0 Fruit Grape 1
1 Fruit 31
WITH source1 AS (
SELECT 'Fruit' foodtype, 'Apple' food, 20 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Apple' food, 30 weight FROM dual UNION
SELECT 'Fruit' foodtype, 'Grape' food, 1 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Carrot' food, 40 weight FROM dual UNION
SELECT 'Veg' foodtype, 'Leek' food, 20 weight FROM dual
)
SELECT grouping(s.food) lv, s.foodtype, s.food,
CASE WHEN grouping(s.food)=1 THEN
sum(CASE WHEN grouping(s.food)=1 THEN 0 ELSE max(s.weight) END) OVER (PARTITION BY s.foodtype ORDER BY s.food)
ELSE
max(s.weight)
END weight
FROM source1 s
GROUP BY s.foodtype, ROLLUP (s.food)
老实说,我也不是100%肯定我喜欢这个答案。根据上下文和维护的角度来看,CASE-WHEN语句比多级SELECT语句更难理解。很抱歉,它给出了错误的输出。我只从每种食物类型中获得第一种食物。@cartbeforehorse。您只需要修复partitionby子句。我更新了答案。即使你做了一点修改,你使用的SELECT语句数量也不会比我在问题中使用的更少。你只是用一种不同的方式来嵌套它们。当分解时,这实际上比我在问题中建议的答案更复杂。您已经将lv列添加到源表中,而实际上它根本不是源数据的一部分。要首先获得lv值,首先需要对源数据进行分组。所以事实上,你会得到4条SELECT语句,而不是我的3条,或者3条而不是2条,这取决于你如何计算。巧妙地使用了无界前置和1前置之间的行。@cartbeforehorse,我已经更新了我的答案,并提供了一个使用total select 2的替代解决方案。但这给出了错误的oputput。水果总数是51,而我预期是31。您仍然需要对源进行分组。