如何将Oracle的LISTAGG函数与唯一筛选器一起使用?
我有一张这样的桌子:如何将Oracle的LISTAGG函数与唯一筛选器一起使用?,oracle,group-by,oracle11g,aggregate-functions,Oracle,Group By,Oracle11g,Aggregate Functions,我有一张这样的桌子: group_id name -------- ---- 1 David 1 John 1 Alan 1 David 2 Julie 2 Charles select wm_concat(distinct name) as names from demotable group by group_id 我希望得到以下结果: group_id names ---
group_id name
-------- ----
1 David
1 John
1 Alan
1 David
2 Julie
2 Charles
select wm_concat(distinct name) as names from demotable group by group_id
我希望得到以下结果:
group_id names
-------- -----
1 'Alan, David, John'
2 'Charles, Julie'
我可以使用以下查询:
select group_id,
listagg(name, ',') within group (order by name) as names
from demotable
group by group_id
要得到这个非常相似的结果:
group_id names
-------- -----
1 'Alan, David, David, John'
2 'Charles, Julie'
您知道如何在Listag调用中按唯一性筛选名称吗?我现在没有11g实例,但您不能使用:
SELECT group_id,
LISTAGG(name, ',') WITHIN GROUP (ORDER BY name) AS names
FROM (
SELECT UNIQUE
group_id,
name
FROM demotable
)
GROUP BY group_id
在11g中,您可以使用未记录的函数wm_concat,如下所示:
group_id name
-------- ----
1 David
1 John
1 Alan
1 David
2 Julie
2 Charles
select wm_concat(distinct name) as names from demotable group by group_id
超级简单的答案-解决 我的完整答案是,它现在内置在一些oracle版本中
select group_id,
regexp_replace(
listagg(name, ',') within group (order by name)
,'([^,]+)(,\1)*(,|$)', '\1\3')
from demotable
group by group_id;
这仅在将分隔符指定为“,”而不是“,”ie时有效
仅适用于逗号后没有空格的情况。如果你想在逗号后面加空格,下面是一个例子
select
replace(
regexp_replace(
regexp_replace('BBall, BBall, BBall, Football, Ice Hockey ',',\s*',',')
,'([^,]+)(,\1)*(,|$)', '\1\3')
,',',', ')
from dual
给予
B足球、足球、冰球我需要这种代码的和平,作为子查询,在基于最外层查询进行聚合之前使用一些数据过滤器,但我无法使用所选的答案代码来实现这一点,因为此过滤器应位于最内层的选择三级查询中,而过滤器参数位于最外层的选择一级查询中,这给了我错误ORA-00904:TB_OUTERMOST.COL:无效标识符,因为ANSI SQL声明表引用关联名称的作用域仅为一级深度 我需要一个没有子查询级别的解决方案,下面这个解决方案对我来说非常有用:
with
demotable as
(
select 1 group_id, 'David' name from dual union all
select 1 group_id, 'John' name from dual union all
select 1 group_id, 'Alan' name from dual union all
select 1 group_id, 'David' name from dual union all
select 2 group_id, 'Julie' name from dual union all
select 2 group_id, 'Charlie' name from dual
)
select distinct
group_id,
listagg(name, ',') within group (order by name) over (partition by group_id) names
from demotable
-- where any filter I want
group by group_id, name
order by group_id;
以下内容未记录,oracle不推荐。 并且不能在函数中应用,显示错误
select wm_concat(distinct name) as names from demotable group by group_id
问候
齐亚看看这篇文章中被接受的答案:不完全一样。。这个问题的答案需要修改以回答另一个问题。这并不是说你不能在那里学到一些东西来应用到这个问题上……这是我在这个问题上的第一个想法,看看相关的DBA问题。在这个简单的数据上,根据autotrace,成本是相同的。感谢您的回答!这是问题的正确答案。不幸的是,我的问题公式不够精确,这对我的实际问题没有帮助,因为我需要这个表中的其他列,我不能用唯一运算符隐藏。很好-很痛苦,但它可以工作。你应该看到我的疑问,这只是一小片:哦,我们编织了一张多么纠结的网:真无聊,不要用WM_CONCAT!我被它在不同小调之间的行为变化所咬!Oracle 11.2.0.1与11.2.0.2的版本,Oracle决定WM_CONCAT应返回CLOB类型Yes返回CLOB-不是字符串-仅供参考仅供参考。。。12c及更高版本不再支持。我使用Oracle regexp有一段时间了,但我不是专家,也不知道这里发生了什么,尤其是模式字符串中的\1。有人能解释一下这里发生了什么事吗?提前谢谢。事实上,如果重复的值不是listagg结果中的前2个值,那么这对我不起作用。例如:此运动列表适用于重复棒球的情况:棒球、篮球-男性、足球、冰球-男性,但不适用于:曲棍球、极限飞盘俱乐部-女性、极限飞盘俱乐部-女性选择regexp_替换“场地曲棍球、极限飞盘俱乐部-女性、极限飞盘俱乐部-女性”、“[^,]+、\1+”,“\1”来自双回程曲棍球,终极飞盘俱乐部-女性似乎很有用。\1是圆括号[^,]+中的第一个匹配词-除了逗号以外的任何词。因此,将\1\1替换为\1删除重复项。如果您不了解regexp是一门黑色艺术,请不要担心。您的权利人还没有时间去做它。。!defalut的WM_concat将无法在Oracle12g上工作,这是一个不推荐使用的函数。在11g之前,它可以正常工作