我有一个名称和数值的表,我想对按名称分组的值进行求和。这部分很简单:
SELECT
name,
SUM(my_value) "MyValue"
FROM my_table
GROUP BY name
但我的价值观中也有“无限”的字符串。当组中出现“无限制”时,我只想选择“无限”值,而不是任何总和。这是我用UNION想出来的,但我知道有更好的方法:
SELECT
name,
MAX("MyValue")
FROM (
SELECT
name,
'UNLIMITED' "MyValue"
FROM my_table
WHERE my_value = 'UNLIMITED'
GROUP BY name
UNION
SELECT
name,
TO_CHAR(SUM(
CASE WHEN my_value = 'UNLIMITED'
THEN '0'
ELSE my_value END
)) "MyValue"
FROM my_table
GROUP BY name
) t
GROUP BY name
请查看SqlFiddle以获取真实示例。
示例表
NAME MY_VALUE
name1 50
name1 20
name2 30
name2 UNLIMITED
想要的结果示例
NAME SUM("MYVALUE")
name1 70
name2 UNLIMITED
这是表达逻辑的一种非常简单的方法:
SELECT name,
(CASE WHEN MAX(my_value) = 'UNLIMITED' THEN 'UNLIMITED'
ELSE TO_CHAR(SUM(CASE WHEN my_value <> 'UNLIMITED' THEN my_value END))
END)
FROM my_table
GROUP BY name;
这使用了字符在数字后排序的事实。
或者类似的逻辑:
SELECT name,
(CASE WHEN COUNT(*) <> COUNT(NULLIF(my_value, 'UNLIMITED')) THEN 'UNLIMITED'
ELSE TO_CHAR(SUM(NULLIF(my_value, 'UNLIMITED')))
END)
FROM my_table
GROUP BY name;
使用窗口函数的一种方法。
SELECT DISTINCT
name,
CASE WHEN sum(case when my_value = 'UNLIMITED' then 1 else 0 end) over(partition by name) >= 1
THEN 'UNLIMITED'
ELSE cast(sum(case when my_value = 'UNLIMITED' then 0 else cast(my_value as number) end) over(partition by name)
as varchar(255))
end as myval
FROM my_table
这有效
create table tempxx (a nvarchar2(10), b nvarchar2(20))
insert into tempxx values ('a', 50);
insert into tempxx values ('a', 20);
insert into tempxx values ('b', 30);
insert into tempxx values ('b', 'UNLIMITED');
SELECT allt.a, decode(ut.max, NULL, to_char(allt.sum), to_char(ut.max)) as val
From
((SELECT
a,
sum(decode(b, 'UNLIMITED', 0, b)) sum
FROM tempxx
Group by a) allT left join
(SELECT
a,
Max(b) max
FROM tempxx
WHERE b = 'UNLIMITED'
Group by a) ut on allt.a = ut.a)
一个VAL ------------ b无限 一个70
基本上,选择左侧的所有行并仅使用无限制连接。如果无限记录为空,请保留左侧,否则采用无限数据