Sql listagg查询结果不同值
我有这样的桌子 +----------------------------+----------------------------+ | Customer_ref(varchar2(40)) | Event_source-varchar2(40)) | +----------------------------+----------------------------+ | ctx10000012 | 12474748,1247574,1247674 | | ctx10000013 | 12474748,12474749,12474750 | +----------------------------+----------------------------+ 表的输出应该是 +----------------------------+----------------------------+ | Customer_ref(varchar2(40)) | Event_source-varchar2(40)) | +----------------------------+----------------------------+ | ctx10000012 | 12474748,1247574,1247674 | | ctx10000013 | 12474748 - 12474750 | +----------------------------+----------------------------+ 如何在不使用with as table select的单选择查询中执行此操作。因为我在游标内使用此选择查询Sql listagg查询结果不同值,sql,oracle,Sql,Oracle,我有这样的桌子 +----------------------------+----------------------------+ | Customer_ref(varchar2(40)) | Event_source-varchar2(40)) | +----------------------------+----------------------------+ | ctx10000012 | 12474748,1247574,1247674 | |
非常感谢您的帮助。这里没有内置的功能来帮助您。因此,编写一个名为ranges_string或任何您喜欢的名称的PL/SQL函数,将字符串从“1,2,3,5,7,8,9”转换为“1-3,5,7-9”或您需要的任何形式,然后在select语句中调用它:
select ranges_string( listagg(event_source, ', ') within group(order by event_source) )
from
(
select distinct customer_ref, event_source from custeventsource
where customer_ref = acc.customer_ref and end_dtm is null
);
编辑:这里有一个转换为范围的函数,例如,将“1,2,3,6,7,8,10,12,13,14”转换为“1-3,6-8,10,12-14”。我没有花太多时间在它上面,所以它肯定不是很好,所以请随意更改它:-
create or replace function convert_ranges(vi_numbers varchar2) return varchar2 is
type table_of_integer is table of integer index by binary_integer;
v_numbers table_of_integer;
v_ranges varchar2(4000);
v_pos integer;
v_count integer;
begin
-- Tokenize
select regexp_substr(vi_numbers, '[^,]+', 1, level) as num
bulk collect into v_numbers
from dual
connect by regexp_substr(vi_numbers, '[^,]+', 1, level) is not null;
-- Collect
v_ranges := v_numbers(1);
v_pos := 2;
while v_pos <= v_numbers.count loop
v_count := 0;
while v_pos <= v_numbers.count and v_numbers(v_pos) = v_numbers(v_pos-1) + 1 loop
v_count := v_count + 1;
v_pos := v_pos + 1;
end loop;
if v_count > 0 then
v_ranges := v_ranges || '-' || v_numbers(v_pos-1);
end if;
if v_pos <= v_numbers.count then
v_ranges := v_ranges || ',';
v_ranges := v_ranges || v_numbers(v_pos);
v_pos := v_pos + 1;
end if;
end loop;
return v_ranges;
end convert_ranges;
不带out的单选查询使用as表select。因为我在游标内使用此select查询。这是什么意思?你能把不起作用的示例代码放进去吗?@Pratik With在single select查询中,我只想给出eventsoucre是否在序列中的输出。如果序列需要以“-”作为分隔符。请各位。。。请帮我解决这个问题..我需要你的帮助..你能帮我写ranges\u string函数吗?因为我是sql的新手。我添加了一个函数,或多或少满足了你的需要。希望这有帮助。顺便说一句:如果你发布了一个新的请求,而不是在已经解决的请求中添加评论,我相信你会得到立即的帮助。如果他们只看到你的请求,肯定有很多人会很快提供这样的功能。
create or replace function convert_ranges(vi_numbers varchar2) return varchar2 is
type table_of_integer is table of integer index by binary_integer;
v_numbers table_of_integer;
v_ranges varchar2(4000);
v_pos integer;
v_count integer;
begin
-- Tokenize
select regexp_substr(vi_numbers, '[^,]+', 1, level) as num
bulk collect into v_numbers
from dual
connect by regexp_substr(vi_numbers, '[^,]+', 1, level) is not null;
-- Collect
v_ranges := v_numbers(1);
v_pos := 2;
while v_pos <= v_numbers.count loop
v_count := 0;
while v_pos <= v_numbers.count and v_numbers(v_pos) = v_numbers(v_pos-1) + 1 loop
v_count := v_count + 1;
v_pos := v_pos + 1;
end loop;
if v_count > 0 then
v_ranges := v_ranges || '-' || v_numbers(v_pos-1);
end if;
if v_pos <= v_numbers.count then
v_ranges := v_ranges || ',';
v_ranges := v_ranges || v_numbers(v_pos);
v_pos := v_pos + 1;
end if;
end loop;
return v_ranges;
end convert_ranges;