如何创建一个新列,返回表格中每行中不同值的数量?例如,
ID Description Pay1 Pay2 Pay3 #UniquePays
1 asdf1 10 20 10 2
2 asdf2 0 10 20 3
3 asdf3 100 100 100 1
4 asdf4 0 10 3
查询可能会返回> 1百万行,因此需要有些效率。总共有8个'Pay'列,它们是NULL或整数。另请注意,'0'应与NULL不同。
到目前为止我能够完成的最多(我刚才意识到这一点甚至不准确)是计算每行中支付条目的总数:
nvl(length(length(Pay1)),0)
+nvl(length(length(Pay2)),0)
+nvl(length(length(Pay3)),0) "NumPays"
典型行只填充了8列中的4列,其余为空,Pay列中的最大整数为'999'(因此长度转换尝试...)
我的SQL技能很原始,但感谢任何帮助!
答案 0 :(得分:4)
如果您拥有或可以创建用户定义的数字表,您可以使用创建集合,使用the set
function删除重复项,然后使用the cardinality
function计算剩余数量值:
SELECT DISTINCT ID_Num
FROM t
WHERE ID_Num NOT IN
(SELECT ID_Num
FROM t
WHERE code = 'C'
OR code = 'D')
要包含所有八个列,只需将额外的列名添加到传递给cardinality(set(t_num(pay1, pay2, pay3))) as uniquepays
构造函数的列表中。
tnum()
将您的样本表演示为CTE:
cardinality(set(t_num(pay1, pay2, pay3, pay4, pay5, pay6, pay7, pay8))) as uniquepays
这是否足够有效,需要测试数百万行。
答案 1 :(得分:2)
这是一种相对简单的方法:
viewControllers
答案 2 :(得分:1)
将每个值拆分为自己的行(就像它应该存储在第一位),然后union
然后向上和(因为union
丢弃重复项)只计算行:
select id, description, count(*) unique_pays from (
select id, description, nvl(pay1, -1) from mytable
union select id, description, nvl(pay2, -1) from mytable
union select id, description, nvl(pay3, -1) from mytable
union select id, description, nvl(pay4, -1) from mytable
union select id, description, nvl(pay5, -1) from mytable
union select id, description, nvl(pay6, -1) from mytable
union select id, description, nvl(pay7, -1) from mytable
union select id, description, nvl(pay8, -1) from mytable
) x
group by id, description
我将空值更改为-1,这样他们就可以干净地参与重复数据删除。
答案 3 :(得分:1)
这是一个只读取基表一次的解决方案,并利用已经按行组织的数据。 (不信任将是低效的,因为这些信息将丢失,导致大量的额外工作。)
它假设所有NULL
被计为相同。如果相反它们应被视为彼此不同,请将-1
中的nvl
更改为不同的值:-1
为Pay1
,-2
为Pay2
等等。
with
inputs( ID, Description, Pay1, Pay2, Pay3 ) as (
select 1, 'asdf1', 10, 20, 10 from dual union all
select 2, 'asdf2', 0, 10, 20 from dual union all
select 3, 'asdf3', 100, 100, 100 from dual union all
select 4, 'asdf4', cast(null as number), 0, 10 from dual
)
-- End of TEST data (not part of solution!) SQL query begins BELOW THIS LINE.
select id, description, pay1, pay2, pay3,
1
+ case when nvl(pay2, -1) not in (nvl(pay1, -1))
then 1 else 0 end
+ case when nvl(pay3, -1) not in (nvl(pay1, -1), nvl(pay2, -1))
then 1 else 0 end
as distinct_pays
from inputs
order by id -- if needed
;
ID DESCRIPTION PAY1 PAY2 PAY3 DISTINCT_PAYS
-- ------------ ------- ------- ------- -------------
1 asdf1 10 20 10 2
2 asdf2 0 10 20 3
3 asdf3 100 100 100 1
4 asdf4 0 10 3
4 rows selected.
答案 4 :(得分:0)
解决方案是:
#uniquePays
。从此
ID Description Pay1 Pay2 Pay3
1 asdf1 10 20 10
制作本:
ID seq Description Pay
1 1 asdf1 10
1 2 asdf1 20
1 3 asdf1 10
这样做,还是需要示例脚本?我最近发布了很多关于旋转和非旋转的内容....似乎是一个受欢迎的需求: - ]
Marco the Sane
答案 5 :(得分:-1)
您可以在插入触发器或存储过程上编写,以计算每个插入语句的唯一值总数,并在唯一列中进行更新。