甲骨文的SQL查询(Analytics(分析)?)
题
我想建立一个查询,例如,一些列是从以前的匹配行建立起来。例如具有以下数据:
CREATE TABLE TEST (SEQ NUMBER, LVL NUMBER, DESCR VARCHAR2(10));
INSERT INTO TEST VALUES (1, 1, 'ONE');
INSERT INTO TEST VALUES (2, 2, 'TWO1');
INSERT INTO TEST VALUES (3, 2, 'TWO2');
INSERT INTO TEST VALUES (4, 3, 'THREE1');
INSERT INTO TEST VALUES (5, 2, 'TWO3');
INSERT INTO TEST VALUES (6, 3, 'THREE2');
COMMIT
我想检索的以下数据。
SEQ L1 L2 L3
1 ONE NULL NULL
2 ONE TWO1 NULL
3 ONE TWO2 NULL
4 ONE TWO2 THREE1
5 ONE TWO3 THREE1
5 ONE TWO3 THREE2
即,对于3行,它本身具有用于L2的值,L1它必须转到包含L1数据的最近的行,在这种情况下的第一行。
我试图寻找的分析和连接子句,但不能让我的头周围的解决方案。结果 任何想法?
解决方案
更新:有一个比我的第一个答案更简单的解决方案。这是更具可读性和更优雅的,因此,我就会把它在这里第一次(由于经常,感谢的汤姆凯特):
SQL> SELECT seq,
2 last_value(CASE
3 WHEN lvl = 1 THEN
4 descr
5 END IGNORE NULLS) over(ORDER BY seq) L1,
6 last_value(CASE
7 WHEN lvl = 2 THEN
8 descr
9 END IGNORE NULLS) over(ORDER BY seq) L2,
10 last_value(CASE
11 WHEN lvl = 3 THEN
12 descr
13 END IGNORE NULLS) over(ORDER BY seq) L3
14 FROM TEST;
SEQ L1 L2 L3
---------- ---------- ---------- ----------
1 ONE
2 ONE TWO1
3 ONE TWO2
4 ONE TWO2 THREE1
5 ONE TWO3 THREE1
6 ONE TWO3 THREE2
以下是我初始溶液:
SQL> SELECT seq,
2 MAX(L1) over(PARTITION BY grp1) L1,
3 MAX(L2) over(PARTITION BY grp2) L2,
4 MAX(L3) over(PARTITION BY grp3) L3
5 FROM (SELECT seq,
6 L1, MAX(grp1) over(ORDER BY seq) grp1,
7 L2, MAX(grp2) over(ORDER BY seq) grp2,
8 L3, MAX(grp3) over(ORDER BY seq) grp3
9 FROM (SELECT seq,
10 CASE WHEN lvl = 1 THEN descr END L1,
11 CASE WHEN lvl = 1 AND descr IS NOT NULL THEN ROWNUM END grp1,
12 CASE WHEN lvl = 2 THEN descr END L2,
13 CASE WHEN lvl = 2 AND descr IS NOT NULL THEN ROWNUM END grp2,
14 CASE WHEN lvl = 3 THEN descr END L3,
15 CASE WHEN lvl = 3 AND descr IS NOT NULL THEN ROWNUM END grp3
16 FROM test))
17 ORDER BY seq;
SEQ L1 L2 L3
---------- ---------- ---------- ----------
1 ONE
2 ONE TWO1
3 ONE TWO2
4 ONE TWO2 THREE1
5 ONE TWO3 THREE1
6 ONE TWO3 THREE2
其他提示
你有仅3个级别(或水平固定数量的)?
如果是这样,你可以使用类似的东西,这是非常低效的,但我相信作品(所以它可能需要稍微改动一个“盲”的代码,我不能从该计算机运行它):
SELECT COUNTER.SEQ AS SEQ, A.DESCR AS L1, B.DESCR AS L2, C.DESCR AS L3
FROM TABLE AS COUNTER, TABLE AS A, TABLE AS B, TABLE AS C
WHERE
A.SEQ =
(SELECT MAX(D.SEQ) FROM TABLE AS D
WHERE D.LVL = 1 AND D.SEQ <= COUNTER.SEQ) AND
B.SEQ =
(SELECT MAX(D.SEQ) FROM TABLE AS D
WHERE D.LVL = 2 AND D.SEQ <= COUNTER.SEQ) AND
C.SEQ =
(SELECT MAX(D.SEQ) FROM TABLE AS D
WHERE D.LVL = 3 AND D.SEQ <= COUNTER.SEQ)
要使用连接子句你实际上需要betwean行一些链接。所以应该有一些列,将有链接到上一行有想要的价值。随着这些领域它是有点难以作出一个选择,因为你需要有2子查询的每一行检查等级别。
我会用PL / SQL程序,如果它是合适的。
declare
cursor c_cur is
select * from test order by seq asc;
lvl1 test.descr%type := null;
lvl2 test.descr%type := null;
lvl3 test.descr%type := null;
begin
for rec in c_cur loop
if rec.lvl = 1 then
lvl1 := rec.descr;
elsif rec.lvl = 2 then
lvl2 := rec.descr;
elsif rec.lvl = 3 then
lvl3 := rec.descr;
end if;
dbms_output.put_line(rec.seq||','||nvl(lvl1, 'null')||','||nvl(lvl2, 'null')||','||nvl(lvl3, 'null'));
end loop;
end;
/
不隶属于 StackOverflow