我有一张桌子:
表1
id col val rec_pos
1 Test 1 10 1
1 Test 2 20 2
1 Test 3 30 3
1 Test 2 20 4
1 Empty 0101 5
1 Invalid 1011 6
2 Test 4 30 2
2 Test 5 30 3
2 Test 6 30 4
2 Test 5 30 5
2 Empty 11101 6
2 Invalid 10101 7
3 Test 7 30 5
3 Test 8 30 6
3 Test 8 30 7
3 Test 8 30 8
3 Empty 11110101 9
3 Invalid 10010101 10
4 Test 9 30 3
4 Empty 1101 5
4 Invalid 1011 6
对于每个唯一的id
,我需要获取val
='Empty'的col
,然后使用rec_pos
,添加一个名为empty
的新列并添加适当的值。
等同于无效,对于每个唯一的id
,我需要为val
='Invalid'抓取col
,然后使用rec_pos
,添加一个名为{ {1}}并添加适当的值。
示例:
对于id = 1,col =空,val = 0101
对于id = 4,col =空,val = 1101
输出为:
invalid
如何读取值,然后将其适当地分配给具有相同ID的各自rec_pos?
答案 0 :(得分:2)
测试用例(仅适用于ID
的第1和第4个;不太喜欢输入):
SQL> create table test
2 (id number,
3 col varchar2(10),
4 val varchar2(10),
5 rec_pos number,
6 empty number,
7 invalid number);
Table created.
SQL> insert into test (id, col, val, rec_pos)
2 (select 1, 'test 1', '10' , 1 from dual union all
3 select 1, 'test 2' , '20' , 2 from dual union all
4 select 1, 'test 3' , '30' , 3 from dual union all
5 select 1, 'test 2' , '20' , 4 from dual union all
6 select 1, 'empty' , '0101', 5 from dual union all
7 select 1, 'invalid', '1011', 6 from dual union all
8 --
9 select 4, 'test 9' , '30' , 3 from dual union all
10 select 4, 'empty' , '1101', 5 from dual union all
11 select 4, 'invalid', '1011', 6 from dual
12 );
9 rows created.
SQL> select * From test;
ID COL VAL REC_POS EMPTY INVALID
---------- ---------- ---------- ---------- ---------- ----------
1 test 1 10 1
1 test 2 20 2
1 test 3 30 3
1 test 2 20 4
1 empty 0101 5
1 invalid 1011 6
4 test 9 30 3
4 empty 1101 5
4 invalid 1011 6
9 rows selected.
SQL>
更新声明:
SQL> update test e set
2 e.empty = (select nvl(x.digit, 0)
3 from ( select t.id,
4 substr(t.val, column_value, 1) digit,
5 column_value rec_pos
6 from test t join
7 table(cast(multiset(select level from dual
8 connect by level <= (select max(t1.rec_pos)
9 from test t1
10 where t1.id = t.id
11 )
12 ) as sys.odcinumberlist ))
13 on 1 = 1
14 where t.col = 'empty'
15 ) x
16 where x.id = e.id
17 and x.rec_pos = e.rec_pos
18 ),
19 --
20 e.invalid = (select nvl(x.digit, 0)
21 from ( select t.id,
22 substr(t.val, column_value, 1) digit,
23 column_value rec_pos
24 from test t join
25 table(cast(multiset(select level from dual
26 connect by level <= (select max(t1.rec_pos)
27 from test t1
28 where t1.id = t.id
29 )
30 ) as sys.odcinumberlist ))
31 on 1 = 1
32 where t.col = 'invalid'
33 ) x
34 where x.id = e.id
35 and x.rec_pos = e.rec_pos
36 );
9 rows updated.
SQL>
它是做什么的?
VAL
并将其拆分为行SUBSTR
的REC_POS
的最大值ID
确定,因此以后可以在更新NVL
时使用EMPTY
(或INVALID
)列结果:
SQL> select * from test;
ID COL VAL REC_POS EMPTY INVALID
---------- ---------- ---------- ---------- ---------- ----------
1 test 1 10 1 0 1
1 test 2 20 2 1 0
1 test 3 30 3 0 1
1 test 2 20 4 1 1
1 empty 0101 5 0 0
1 invalid 1011 6 0 0
4 test 9 30 3 0 1
4 empty 1101 5 0 0
4 invalid 1011 6 0 0
9 rows selected.
SQL>
答案 1 :(得分:2)
我认为这可以为您提供所需的输出。
SELECT t.id,
t.col,
t.val,
t.rec_pos,
NVL(e.empty, 0) AS empty,
NVL(i.invalid, 0) AS invalid
FROM
table1 t
LEFT
JOIN (SELECT DISTINCT t.id, levels.column_value AS rec_pos, SUBSTR(val, levels.column_value, 1) AS empty
FROM table1 t, TABLE(CAST(MULTISET(SELECT level FROM dual CONNECT BY level <= LENGTH(val)) AS sys.OdciNumberList)) levels
WHERE t.col = 'Empty' ORDER BY id) e ON e.id = t.id AND e.rec_pos = t.rec_pos
LEFT
JOIN (SELECT DISTINCT t.id, levels.column_value AS rec_pos, SUBSTR(val, levels.column_value, 1) AS invalid
FROM table1 t, TABLE(CAST(MULTISET(SELECT level FROM dual CONNECT BY level <= LENGTH(val)) AS sys.OdciNumberList)) levels
WHERE t.col = 'Invalid' ORDER BY id) i ON i.id = t.id AND i.rec_pos = t.rec_pos
ORDER
BY t.id, t.rec_pos;
答案 2 :(得分:2)
如果位置由rec_pos
确定,那么您可以简单地将susbtr
与分析性max
结合使用:
select t.*,
nvl(substr(max(case col when 'Empty' then val end)
over (partition by id), rec_pos, 1), 0) empty,
nvl(substr(max(case col when 'Invalid' then val end)
over (partition by id), rec_pos, 1), 0) invalid
from table1 t
或具有相关子查询:
select t.*,
nvl(substr((select val
from table1 e
where e.id = t.id and col= 'Empty'), rec_pos, 1), 0) empty,
nvl(substr((select val
from table1 i
where i.id = t.id and col= 'Invalid'), rec_pos, 1), 0) invalid
from table1 t
如果empty
和invald
是表中的真实列,则对以上任何查询使用简单合并来更新它们。但是最好查看一列是由其他人的计算得出的结果。