正则表达式,用于在均匀分布的多行中获取单行的输出

时间:2015-12-09 15:29:55

标签: sql oracle

我的输出格式为管道分隔格式的单行 chq no, amount, bene name 例如:

123,100.00,test1 | 234,200.00,test2 | 345,300.00,test4 | ......... n

我希望根据记录数量来格式化输出。如果我的查询返回50个管道分隔值(见下面的sql),那么我希望输出平均分布在10行中,每行10条记录,依此类推。

123,100.00,test1 | 234,200.00,test2 | 345,300.00,test4 
111,100.00,test5 | 222,200.00,test6 | 333,300.00,test7
444,100.00,test3 | 555,200.00,test9 | 666,300.00,test8

我测试了一个查询,但输出不符合预期

WITH w AS (
select count(*), ACCOUNTNO, rtrim (xmlagg (xmlelement (a,info || ' | ')).extract ('//text()'), ',')  info1
from (
select ACCOUNTNO, CHECKNO || ' , ' || AMOUNT || ' , ' || BENE_NAME info from test_alert_log
where trunc(TXNDATE) = '30-NOV-2015' and trim(ACCOUNTNO) = '1234567890'
)
group by ACCOUNTNO)

SELECT regexp_substr(info1,'[^|]+', 1, column_value)
  FROM w,
       TABLE(
         CAST(
           MULTISET(SELECT LEVEL 
                       FROM dual  
                    CONNECT BY LEVEL <= LENGTH(info1) + LENGTH(replace(info1, '|')) + 1
                   ) AS sys.OdciNumberList
         )
       )
WHERE regexp_substr(info1,'[^|]+', 1, column_value) IS NOT NULL 

1 个答案:

答案 0 :(得分:0)

我相信这会成功。从第14行开始,连接通过首先计算分隔符并添加1以获取字段数,然后除以2(在我的示例中每行所需的“记录数”)来计算需要多少行输出并通过CEIL()(基本上向上舍入)运行它来处理部分行(如果有的话)。

然后看第7行,它输出至少为1的模式的column_value-eth(实际上是row-eth),但不超过2(必须等于前一段中的2)模式的0或更多字符不是分隔符后面的管道或行的末尾。这是贪婪的,所以如果它们可用,它将获得2。消耗尾随空格/管道/空间(诅咒Oracle在其正则表达式中没有前瞻)并且必须从输出中删除,所以我只使用rtrim()。输出周围的方括号仅用于说明不存在空格,当然应将其移除以进行生产。

SQL> with w(info1) as (
  2    select '123,100.00,test1 | 234,200.00,test2 | 345,300.00,test3 | 111,100.00,test4 | ' ||
  3           '222,200.00,test5 | 333,300.00,test6 | 444,100.00,test7 | 555,200.00,test8 | ' ||
  4           '666,300.00,test9' from dual
  5  )
  6  SELECT column_value, '[' ||
  7         rtrim(regexp_substr(info1, '(([^|]*( \| |$)){1,2})', 1, column_value, NULL, 1), ' | ') ||
  8         ']' output
  9  FROM w,
 10       TABLE(
 11         CAST(
 12           MULTISET(SELECT LEVEL
 13                    FROM dual
 14                    CONNECT BY LEVEL <= ceil((REGEXP_COUNT(info1, ' \| ') + 1) / 2) -- Calculates rows
 15                   ) AS sys.OdciNumberList
 16             )
 17            );

COLUMN_VALUE OUTPUT
------------ ----------------------------------------
           1 [123,100.00,test1 | 234,200.00,test2]
           2 [345,300.00,test3 | 111,100.00,test4]
           3 [222,200.00,test5 | 333,300.00,test6]
           4 [444,100.00,test7 | 555,200.00,test8]
           5 [666,300.00,test9]

SQL>

因此,第7行和第14行的数字“2”只需要更改为你想在一条线上显示的许多“记录”,它应该适合你。让我们知道它是如何工作的。