我有一张桌子
表1
u_a_id e_id e_nm e_val e_seq
1 104 test 100 4
1 102 test2 x 2
1 102 test2 (null) 1
1 104 test (null) 1
2 102 test2 (null) 2
2 102 test2 (null) 1
2 104 test 101 1
2 104 test 102 2
我首先需要对每个u_a_id按e_id
,e_seq
进行排序,并将每个(null)
标识为1,然后创建如下的位图。
例如
因此,对于u_a_id = 1,添加新行-EMPTY = 1010
输出为:
u_a_id e_id e_nm e_val e_seq
1 104 test 100 4
1 102 test2 x 2
1 102 test2 (null) 1
1 104 test (null) 1
1 (null) EMPTY 1010 (null)
2 102 test2 (null) 2
2 102 test2 (null) 1
2 104 test 101 1
2 104 test 102 2
2 (null) EMPTY 1100 (null)
Oracle SQL中有一种方法可以做到吗?
答案 0 :(得分:3)
您可以使用LISTAGG
进行字符串聚合,并使用GROUPING SETS
:
SELECT U_A_ID, E_ID
,CASE WHEN GROUPING_ID(U_A_ID, E_ID, E_NM, E_VAL, E_SEQ) = 15
THEN 'EMPTY'
ELSE E_NM END AS E_NM
,CASE WHEN GROUPING_ID(U_A_ID, E_ID, E_NM, E_VAL, E_SEQ) = 15
THEN LISTAGG(NVL2(E_VAL, '1', '0'),'') WITHIN GROUP (ORDER BY E_ID DESC, E_SEQ DESC)
ELSE E_VAL END AS E_VAL
,E_SEQ
FROM E
GROUP BY GROUPING SETS ((U_A_ID, E_ID, E_NM, E_VAL, E_SEQ), (U_A_ID))
ORDER BY U_A_ID, E_ID, E_SEQ;
答案 1 :(得分:1)
这应该按照您的要求执行,创建一个带有1和0的文本字符串。 请注意,将UNION放在此处只是为了复制与数据混合的预期结果行。您可以删除UNION及其后面的SQL位。
创建适当的数字位图而不是文本字符串一样容易。
设置:
create table e(
u_a_id integer,
e_id integer,
e_nm varchar2(10),
e_val varchar2(10),
e_seq integer
);
INSERT INTO E(U_A_ID, E_ID, E_NM, E_VAL, E_SEQ) VALUES (1,102,'test2','x',2);
INSERT INTO E(U_A_ID, E_ID, E_NM, E_VAL, E_SEQ) VALUES (1,102,'test2',NULL,1);
INSERT INTO E(U_A_ID, E_ID, E_NM, E_VAL, E_SEQ) VALUES (1,104,'test','100',4);
INSERT INTO E(U_A_ID, E_ID, E_NM, E_VAL, E_SEQ) VALUES (1,104,'test',NULL,1);
INSERT INTO E(U_A_ID, E_ID, E_NM, E_VAL, E_SEQ) VALUES (2,102,'test2',NULL,1);
INSERT INTO E(U_A_ID, E_ID, E_NM, E_VAL, E_SEQ) VALUES (2,102,'test2',NULL,2);
INSERT INTO E(U_A_ID, E_ID, E_NM, E_VAL, E_SEQ) VALUES (2,104,'test','101',1);
INSERT INTO E(U_A_ID, E_ID, E_NM, E_VAL, E_SEQ) VALUES (2,104,'test','102',2);
查询:
with x as(
-- This gets the rows with a "row number" within each U_A_ID group
select e.*,row_number() over (PARTITION BY u_a_id ORDER BY e_id, e_seq) R from e
),
y as(
-- This produces the bit, as a character, based on the E_VAL column
select x.u_a_id, x.e_id, x.e_seq, nvl2(x.e_val, '1', '0') as bit from x
),
z as(
-- This concatenates the bits, in the same reversed order that you provided
select u_a_id, listagg(bit, '') within group (order by e_id desc, e_seq desc) bits from y group by u_a_id
)
select u_a_id, null as e_id, 'EMPTY' as e_nm, to_char(bits) as e_val, null as e_seq from z
union
select u_a_id, e_id, e_nm, e_val, e_seq from e
order by u_a_id, e_id nulls last, e_seq
/
答案 2 :(得分:0)
以下内容会生成您的“位图”:
select distinct t2.u_a_id,
(select case when t1.e_val is null then '1' else '0' end as [text()]
from table1 as t1
where t1.u_a_id = t2.u_a_id
order by u_a_id, e_id, e_seq
for xml path ('')
) as bitmap
from table1 as t2
答案 3 :(得分:0)
最短的将会是
SELECT * FROM E -- Get the unchanged records
UNION ALL
-- And add the new rows:
SELECT U_A_ID
, NULL
, 'EMPTY'
, listagg(NVL2(E_VAL, 0, 1),'') WITHIN GROUP (ORDER BY e_id, e_seq)
, NULL
FROM e
GROUP BY u_a_id
ORDER BY 1,2 nulls last, 5 nulls last -- Order to get your desired order