Java oracle中acolumn的三个字符串中的公共子字符串合并

Java oracle中acolumn的三个字符串中的公共子字符串合并,java,string,oracle,group-by,Java,String,Oracle,Group By,我有以下三栏: Dated status count 01-02-13 1A + 2B + 73PLO 76 01-02-13 29A + 17ACB 46 01-02-13 9PLO + 11B + 5TY 25 02-02-13 18FGH + 23B +

我有以下三栏:

Dated                    status                count 
01-02-13              1A + 2B + 73PLO           76
01-02-13              29A + 17ACB               46
01-02-13              9PLO + 11B + 5TY          25
02-02-13              18FGH + 23B + 4ACB        45
02-02-13              8ACB + 12A + 2FGH         22
02-02-13              6A + 2B + 42ACB           50
03-02-13              .....                     ...
............
因此,我的最终结果应该为特定的“日期”添加三个字符串“状态”,但请记住特定日期的三个字符串的公共子字符串,如下所示-

dated                     status                            count
01-02-13         30A + 13B + 82PLO + 17ACB + 5TY             147
02-02-13         20FGH + 25B + 73PLO + 54ACB + 18A           117
03-02-13              ......(and similarly)                  ....
在这里,我通过添加计数和合并“状态”在“日期”上创建了一个group by表达式,但实际上我无法达到这一点。。。。 需要一些帮助

Oracle 11g R2架构设置:

问题1:

一个对Oracle 11g R1有效的SQL解决方案,尽管如果您将REGEXP\u COUNT替换为LENGTHREGEXP\u REPLACEstatus,“\d+[A-Z]+\+\124;$”,“X”,那么您应该能够在Oracle 9i中使用它:

WITH counts AS (
  SELECT Dated,
         SUM( "count" ) AS total_count
  FROM Data
  GROUP BY Dated
),
split_statuses AS (
  SELECT DISTINCT
         Dated,
         TO_NUMBER( REGEXP_SUBSTR( status, '(\d+)([A-Z]+)', 1, LEVEL, NULL, 1) ) AS num_status,
         REGEXP_SUBSTR( status, '(\d+)([A-Z]+)', 1, LEVEL, NULL, 2) AS val_status
  FROM   Data
  CONNECT BY LEVEL <= REGEXP_COUNT(status, '(\d+)([A-Z]+)')
),
summed_statuses AS (
  SELECT Dated,
         SUM( num_status ) || val_status AS totaled_status,
         val_status
  FROM   split_statuses
  GROUP BY Dated, val_status
),
indexed_summed_statuses AS (
  SELECT Dated,
         totaled_status,
         ROW_NUMBER() OVER ( PARTITION BY Dated ORDER BY val_status ) AS idx
  FROM   summed_statuses
),
grouped_statuses AS (
  SELECT Dated,
         SYS_CONNECT_BY_PATH( totaled_status, ' + ' ) AS status,
         idx
  FROM   indexed_summed_statuses
  START WITH idx = 1
  CONNECT BY PRIOR idx + 1 = idx AND prior Dated = Dated
),
max_grouped_statuses AS (
  SELECT Dated,
         SUBSTR( MAX( status ) KEEP ( DENSE_RANK LAST ORDER BY idx ), 4 ) AS status
  FROM   grouped_statuses
  GROUP BY Dated
)
SELECT m.Dated,
       status,
       total_count
FROM   max_grouped_statuses m
       INNER JOIN
       counts c
       ON ( m.Dated = c.Dated )
ORDER BY Dated
问题2:

Oracle 11g R2提供了一个更简单的解决方案:

WITH counts AS (
  SELECT Dated,
         SUM( "count" ) AS total_count
  FROM Data
  GROUP BY Dated
),
split_statuses AS (
  SELECT DISTINCT
         Dated,
         TO_NUMBER( REGEXP_SUBSTR( status, '(\d+)([A-Z]+)', 1, LEVEL, NULL, 1) ) AS num_status,
         REGEXP_SUBSTR( status, '(\d+)([A-Z]+)', 1, LEVEL, NULL, 2) AS val_status
  FROM   Data
  CONNECT BY LEVEL <= REGEXP_COUNT(status, '(\d+)([A-Z]+)')
),
summed_statuses AS (
  SELECT Dated,
         SUM( num_status ) || val_status AS totaled_status,
         val_status
  FROM   split_statuses
  GROUP BY Dated, val_status
),
grouped_statuses AS (
  SELECT Dated,
         LISTAGG( totaled_status, ' + ') WITHIN GROUP (ORDER BY val_status) AS status
  FROM   summed_statuses
  GROUP BY Dated
)
SELECT g.Dated,
       status,
       total_count
FROM   grouped_statuses g
       INNER JOIN
       counts c
       ON ( g.Dated = c.Dated )
ORDER BY Dated

没有完全测试,但我认为这是您所要求的,我没有考虑所有的测试用例,可能在某些情况下总计数不同,但状态分组是正确的

 SELECT dated
      ,LISTAGG(num||val, ' + ') WITHIN GROUP (ORDER BY val) status
     ,MAX(cnt) "count"
 FROM
  --middle section start
  (
    SELECT dated
          ,SUM(regexp_substr(sub_status,'[0-9]+')) num
         ,regexp_substr(sub_status,'[A-Z]+')val,MAX(cnt) cnt
     FROM
        --inner section start
        (
         SELECT DISTINCT dated
                        ,TRIM(REGEXP_SUBSTR( status, '[^+]+', 1, LEVEL)) sub_status
                        ,SUM(DISTINCT "count") OVER(PARTITION BY dated) cnt
         FROM DATA
        CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(status, '[^+]+')) + 1
         )
         --inner section end 
   GROUP BY dated
           ,regexp_substr(sub_status,'[A-Z]+')
   )
   --middle section end
 GROUP BY dated;
内部部分:首先,我尝试将所有不同的值分隔成由+ 然后我进一步分离数值,去掉数字部分和字母部分。 中间部分:我试着根据分组日期列和字母部分来计算数字部分的和。 外部部分:我结合了基于日期列的中间部分的结果,以+ *注*我没有对此进行测试,但这应该是解决此问题的方法,而不是考虑在同一组中具有相同值的计数


请发布您的代码。如果count列在同一日期有重复的值,这将不会返回正确的总和。很好的捕获,谢谢-它现在修复了在重复值上显示count列的正确总和的问题。
WITH counts AS (
  SELECT Dated,
         SUM( "count" ) AS total_count
  FROM Data
  GROUP BY Dated
),
split_statuses AS (
  SELECT DISTINCT
         Dated,
         TO_NUMBER( REGEXP_SUBSTR( status, '(\d+)([A-Z]+)', 1, LEVEL, NULL, 1) ) AS num_status,
         REGEXP_SUBSTR( status, '(\d+)([A-Z]+)', 1, LEVEL, NULL, 2) AS val_status
  FROM   Data
  CONNECT BY LEVEL <= REGEXP_COUNT(status, '(\d+)([A-Z]+)')
),
summed_statuses AS (
  SELECT Dated,
         SUM( num_status ) || val_status AS totaled_status,
         val_status
  FROM   split_statuses
  GROUP BY Dated, val_status
),
grouped_statuses AS (
  SELECT Dated,
         LISTAGG( totaled_status, ' + ') WITHIN GROUP (ORDER BY val_status) AS status
  FROM   summed_statuses
  GROUP BY Dated
)
SELECT g.Dated,
       status,
       total_count
FROM   grouped_statuses g
       INNER JOIN
       counts c
       ON ( g.Dated = c.Dated )
ORDER BY Dated
|                           DATED |                          STATUS | TOTAL_COUNT |
|---------------------------------|---------------------------------|-------------|
| February, 01 2013 00:00:00+0000 | 30A + 18ACB + 13B + 82PLO + 5TY |         193 |
| February, 02 2013 00:00:00+0000 |       18A + 54ACB + 25B + 20FGH |         117 |
 SELECT dated
      ,LISTAGG(num||val, ' + ') WITHIN GROUP (ORDER BY val) status
     ,MAX(cnt) "count"
 FROM
  --middle section start
  (
    SELECT dated
          ,SUM(regexp_substr(sub_status,'[0-9]+')) num
         ,regexp_substr(sub_status,'[A-Z]+')val,MAX(cnt) cnt
     FROM
        --inner section start
        (
         SELECT DISTINCT dated
                        ,TRIM(REGEXP_SUBSTR( status, '[^+]+', 1, LEVEL)) sub_status
                        ,SUM(DISTINCT "count") OVER(PARTITION BY dated) cnt
         FROM DATA
        CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(status, '[^+]+')) + 1
         )
         --inner section end 
   GROUP BY dated
           ,regexp_substr(sub_status,'[A-Z]+')
   )
   --middle section end
 GROUP BY dated;