我有一个奇怪的问题。从这个输入:
ID
1
3
6
8
9
11
23
......我需要得到这个输出:
ID Res
1 1
3 1,3,1
6 1,3,6,3,1
8 1,3,6,8,6,3,1
9 1,3,6,8,9,8,6,3,1
11 1,3,6,8,9,11,9,8,6,3,1
主要问题是我需要在没有 Model子句,分析函数,regexps,CONNECT BY,递归WITH,WM_CONCAT和LISTAGG 的情况下进行查询。这些是业务规则......我想知道是否有办法做到这一点。也许一个函数可以用来收集一些行?或者是我忘记的建筑。任何建议都会有所帮助。
P.S。 PL / SQL也被排除在外
答案 0 :(得分:4)
这是我发现的唯一方法,可以获得具有所有限制的结果;不是那么优雅,但是......
它的基础是使用XML函数构建串联,然后详细说明生成的字符串以获得结果。
使用此表:
create table tab(ID) as (
select 1 from dual union all
select 3 from dual union all
select 6 from dual union all
select 8 from dual union all
select 9 from dual union all
select 11 from dual union all
select 23 from dual
)
此
select id,
rtrim(
replace( replace(
extract(
xmltype(dbms_xmlgen.getxml
(
'select id from (select 1 pos, id from tab where id <=' || id ||
' union all select 2, id from tab where id < ' || id ||
') order by pos, case when pos = 1 then id else -id end')
)
,'/ROWSET/ROW/ID'
)
, '<ID>', '')
, '</ID>', ','
)
, ','
) as result
from tab t1;
给出:
ID RESULT
---------- ------------------------------
1 1
3 1,3,1
6 1,3,6,3,1
8 1,3,6,8,6,3,1
9 1,3,6,8,9,8,6,3,1
11 1,3,6,8,9,11,9,8,6,3,1
23 1,3,6,8,9,11,23,11,9,8,6,3,1
工作原理:内部查询为给定的ID
提供所需顺序的ID
列表,但是作为行而不是连接值;例如,对于ID = 6
,我们有
select id
from (
select 1 pos, id
from tab
where id <= 6
union all
select 2, id
from tab
where id < 6
) order by pos,
case when pos = 1 then id else -id end
给出:
ID
----------
1
3
6
3
1
XML部分用于转换每个ID
的值列表,在单个值(xmltype
)中,replace
/ trim
部分用于从XML中提取数据。
例如,ID=6
的XML:
<?xml version="1.0"?>
<ROWSET>
<ROW>
<ID>1</ID>
</ROW>
<ROW>
<ID>3</ID>
</ROW>
<ROW>
<ID>6</ID>
</ROW>
<ROW>
<ID>3</ID>
</ROW>
<ROW>
<ID>1</ID>
</ROW>
</ROWSET>
但是,我认为这更像是一个练习,而不是我希望在真实系统中看到的一段代码。
答案 1 :(得分:0)
只是为了好玩。我使用案例陈述的例子:
create table test (ID number);
insert into test values(1);
insert into test values(3);
insert into test values(6);
insert into test values(8);
insert into test values(9);
insert into test values(11);
insert into test values(23);
commit;
select id,
case id
when 1 then '1'
when 3 then '1,3,1'
when 6 then '1,3,6,3,1'
when 8 then '1,3,6,8,6,3,1'
when 9 then '1,3,6,8,9,8,6,3,1'
when 11 then '1,3,6,8,9,11,9,8,6,3,1'
end as "Res"
from test
where id <> 23
order by id;
输出:
ID Res
---------- ----------------------
1 1
3 1,3,1
6 1,3,6,3,1
8 1,3,6,8,6,3,1
9 1,3,6,8,9,8,6,3,1
11 1,3,6,8,9,11,9,8,6,3,1
至少它没有使用任何异国情调,这似乎是个问题。我想这是针对某些课程还是考试?
答案 2 :(得分:0)
您可以使用函数创建包,请参阅下面的示例
create table tab_test(ID) as (
select 1 from dual union all
select 3 from dual union all
select 6 from dual union all
select 8 from dual union all
select 9 from dual union all
select 11 from dual
);
create or replace package pkg_test
as
v_id NUMBER;
v_ids VARCHAR2(200);
FUNCTION get_ids (p_id NUMBER) RETURN VARCHAR2;
END;
/
create or replace package body pkg_test
as
FUNCTION get_ids (p_id NUMBER) RETURN VARCHAR2
is
v_rev_text VARCHAR2(200);
BEGIN
IF v_ids IS NULL THEN
v_ids := p_id;
RETURN v_ids;
ELSE
v_ids := v_ids||', '||p_id;
END IF;
SELECT substr(reverse(v_ids), length(p_id) + 1)
into v_rev_text
from dual;
RETURN v_ids||', '||trim(',' from trim(v_rev_text));
END;
END;
/
--Always run this before the select statement,
begin
pkg_test.v_ids := null;
end;
/
select pkg_test.get_ids(id)
from tab_test;
输出:
Result
-----------------------
1
1, 3, 1
1, 3, 6, 3 ,1
1, 3, 6, 8, 6 ,3 ,1
1, 3, 6, 8, 9, 8 ,6 ,3 ,1
1, 3, 6, 8, 9, 11, 9 ,8 ,6 ,3 ,1
选择了6行