2011-10-18 54 views
1
Oracle 10gOracle 10g上,说我有以下列:

SQL - 一列的Unpivot结果

col 
------------------------------------------------------------------------------------------------ 
[1,98]([1,81]([6,100828],[6,101260]),[1,81]([6,100529],[6,101259]),[1,81]([6,101709],[6,100474])) 

我希望显示此结果:

col 
------ 
100828 
101260 
100529 
101259 
101709 
100474 

是否可以使用SQL查询显示此结果?

其实我试过的:

SELECT SUBSTR(col, INSTR(col, ',', 1, 3) + 1, 6) exp_1, 
     SUBSTR(col, INSTR(col, ',', 1, 5) + 1, 6) exp_2, 
     SUBSTR(col, INSTR(col, ',', 1, 8) + 1, 6) exp_3, 
     SUBSTR(col, INSTR(col, ',', 1, 10) + 1, 6) exp_4, 
     SUBSTR(col, INSTR(col, ',', 1, 13) + 1, 6) exp_5, 
     SUBSTR(col, INSTR(col, ',', 1, 15) + 1, 6) exp_6 
    FROM (SELECT '[1,98]([1,81]([6,100828],[6,101260]),[1,81]([6,100529],[6,101259]),[1,81]([6,101709],[6,100474]))' col 
      FROM dual) ; 

EXP_1 EXP_2 EXP_3 EXP_4 EXP_5 EXP_6 
------ ------ ------ ------ ------ ------ 
100828 101260 100529 101259 101709 100474 

但是,返回的exp_%的数量可以是变量并且总是成对的,这意味着另一行可以返回8 exp_%:

SUBSTR(col, INSTR(col, ',', 1, 18) + 1, 6) exp_7 , 
SUBSTR(col, INSTR(col, ',', 1, 20) + 1, 6) exp_8 

exp_%修复次数的建议也非常受欢迎!

谢谢。

回答

2

假设你的表被命名为“富”与“关口”的列名:

with q as (
    select ','||regexp_replace(
     regexp_replace(
      regexp_replace(
       regexp_replace(col, '[[0-9,]*]\(', ''), 
        '\[[0-9],', ''), 
       '[])]', ','), 
     ',,+', 
     ',') a from foo 
) 
select data 
    from (select substr(a, instr(a, ',', 1, rownum) + 1, 6) data 
      from q, 
       (select 1 from q connect by level < length(regexp_replace(a, '[0-9]', ''))) 
     ) 
; 

这里的解释。这很快就会变得复杂,并且可能不会很好地扩展,所以买家要小心。

首先我想摆脱 '[1,98](' 领域。

1 with q as (
    2 select 
    3   regexp_replace(col, '[[0-9,]*]\(', '') 
    4 from foo 
    5 ) 
    6* select * from q 

REGEXP_REPLACE(COL,'[[0-9,]*]\(','') 
------------------------------------------------------------------------------------------------------------------------------------ 
[6,100828],[6,101260])[6,100529],[6,101259])[6,101709],[6,100474])) 

接下来,我想摆脱 '[N' 字段的部分。

1 with q as (
    2 select 
    3  regexp_replace(
    4   regexp_replace(col, '[[0-9,]*]\(', ''), 
    5   '\[[0-9],', '' 
    6  ) a from foo 
    7 ) 
    8* select * from q 

A 
------------------------------------------------------------------------------------------------------------------------------------ 
100828],101260])100529],101259])101709],100474])) 

现在摆脱所有“]”和“)”

1 with q as (
    2 select 
    3  regexp_replace(
    4  regexp_replace(
    5   regexp_replace(col, '[[0-9,]*]\(', ''), 
    6   '\[[0-9],', ''), 
    7   '[])]', ',') 
    8  a from foo 
    9 ) 
10* select * from q 

A 
------------------------------------------------------------------------------------------------------------------------------------ 
100828,,101260,,100529,,101259,,101709,,100474,,, 

摆脱重复的逗号和前面加上一个逗号。

1 with q as (
    2 select ','||regexp_replace(
    3  regexp_replace(
    4  regexp_replace(
    5   regexp_replace(col, '[[0-9,]*]\(', ''), 
    6   '\[[0-9],', ''), 
    7   '[])]', ','), 
    8  ',,+', 
    9  ',') a from foo 
10 ) 
11* select * from q 

A 
------------------------------------------------------------------------------------------------------------------------------------ 
,100828,101260,100529,101259,101709,100474, 

找出它们有多少个字段并为每个字段创建一个行。

1 with q as (
    2 select ','||regexp_replace(
    3  regexp_replace(
    4  regexp_replace(
    5   regexp_replace(col, '[[0-9,]*]\(', ''), 
    6   '\[[0-9],', ''), 
    7   '[])]', ','), 
    8  ',,+', 
    9  ',') a from foo 
10 ) 
11* select 1 from q connect by level < length(regexp_replace(a, '[0-9]', '')) 

    1 
---------- 
    1 
    1 
    1 
    1 
    1 
    1 
    1 

做一个笛卡儿连接与Q(注意这一点,如果有您的表不止一行将无法正常工作。)和子,让您的最终答案。

1 with q as (
    2 select ','||regexp_replace(
    3  regexp_replace(
    4  regexp_replace(
    5   regexp_replace(col, '[[0-9,]*]\(', ''), 
    6   '\[[0-9],', ''), 
    7   '[])]', ','), 
    8  ',,+', 
    9  ',') a from foo 
10 ) 
11 select data 
12 from (select substr(a, instr(a, ',', 1, rownum) + 1, 6) data 
13  from q, 
14   (select 1 from q connect by level < length(regexp_replace(a, '[0-9]', ''))) 
15*  ) 

DATA 
------ 
100828 
101260 
100529 
101259 
101709 
100474 


6 rows selected. 
+0

请注意,在11g中使用pivot/unpivot可能会更容易得多 – RichardJQ

+0

谢谢理查德!这是相当令人印象深刻,即时通讯仍然有点失落,并想问你它也有可能得到每对结果,意味着每行两个,在我们的例子100828,101260和第二行100529,101259等... – mcha

+0

它应该是可能的。如果我有时间,我会看看我能不能想出如何。 – RichardJQ