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;