如何从属性中删除重复的值

时间:2019-07-05 08:56:54

标签: sql oracle

我在一个单元格中有一列具有重复值的列,请告诉我如何仅使用sql或pl / sql删除重复值。

 | Test
-+--------------------------------------------------------------------
 | 999999999(10145) 999999999(10145) 999999999(10145) 999999999(10145)
 |--------------------------------------------------------------------
 | 113307425(2) 310122174(2) 310122174(2) 113307425(2)

2 个答案:

答案 0 :(得分:2)

使用带有反向引用的正则表达式来匹配重复项:

Oracle设置

CREATE TABLE test_data ( value ) AS
SELECT '9999999(12345) 9999999(12345) 9999999(12345) 9999999(12345)' FROM DUAL;

查询

SELECT REGEXP_REPLACE( value, '([^ ]+)( \1)+', '\1' ) AS replaced_value
FROM   test_data

输出

| REPLACED_VALUE |
| :------------- |
| 9999999(12345) |

db <>提琴here


已更新:对于第六次编辑中的新数据:

CREATE TABLE test_data ( value ) AS
SELECT '9999999(12345) 9999999(12345) 9999999(12345) 9999999(12345)' FROM DUAL UNION ALL
SELECT '113307425(2) 310122174(2) 310122174(2) 113307425(2)' FROM DUAL;

查询

使用递归子查询分解子句在字符串中查找术语,然后使用DISTINCT删除重复项,并使用LISTAGG将它们重新组合成单​​个字符串。

WITH bounds ( id, value, start_pos, end_pos ) AS (
  SELECT ROWID,
         value,
         1,
         INSTR( value, ' ', 1 )
  FROM   test_data
UNION ALL
  SELECT id,
         value,
         end_pos + 1,
         INSTR( value, ' ', end_pos + 1 )
  FROM   bounds
  WHERE  end_pos > 0
),
strings ( id, value ) AS (
  SELECT DISTINCT
         id,
         CASE end_pos
           WHEN 0
           THEN SUBSTR( value, start_pos )
           ELSE SUBSTR( value, start_pos, end_pos - start_pos )
         END
  FROM   bounds
)
SELECT LISTAGG( value, ' ' ) WITHIN GROUP ( ORDER BY value ) AS unique_values
FROM   strings
GROUP BY id

输出

| UNIQUE_VALUES             |
| :------------------------ |
| 9999999(12345)            |
| 113307425(2) 310122174(2) |

db <>提琴here

答案 1 :(得分:0)

Oracle允许使用递归子查询因式分解,从而可以反复应用基于正则表达式的替换:

CREATE TABLE test_data ( value ) AS
SELECT '9999999(12345) 9999999(12345) 9999999(12345) 9999999(12345)' FROM DUAL;

WITH rep(n,s,n_maxrep) AS (
    SELECT 1
         , value
         , 1 + LENGTH(REGEXP_REPLACE(value, '[^ ]', ''))
      FROM test_data
 UNION ALL
    SELECT n+1
         , REGEXP_REPLACE ( s, '([^ ]+)(( [^ ]+)*)( \1)+', '\1\2' ) 
         , n_maxrep
      FROM rep
     WHERE n <= n_maxrep
)
SELECT s FROM rep WHERE n = n_maxrep;

说明

该查询反复对单个动词重复项应用相同的基于正则表达式的基本替换。到原始列。在这种情况下,“动词”是连续的非空格字符的最大序列。重复项可以彼此相邻或被其他动词分隔。

此类替换的最大可能数目是预先已知的:n-1用于n动词,当所有动词都相同时。这等于原始值中出现分隔符的次数。

其他所有都是语法糖。 Oracle自己构建嵌套的子查询链。

请注意,限制n_maxrep实际上是1 + <分隔符出现次数>。这是必需的,因为基本情况(n=1不能替代。