【问题标题】:Creating a new column from substrings of original column with different delimiters从具有不同分隔符的原始列的子字符串创建新列
【发布时间】:2021-06-20 04:27:05
【问题描述】:

在我的 Oracle SQL Developer 中,我有一个包含以下“名称”列的表:

| NAME |
--------
Joe Smith
John Doe and Jane Doe
Jenny May, Steven Thomas

我的目标是在新表中创建一个新列,通过分隔 and, 来展平 NAME 表,因此它看起来像:

| NEW_NAME |
------------
Joe Smith
John Doe
Jane Doe
Jenny May
Steven Thomas

我已经掌握了创建分离列的基本逻辑:

SELECT SUBSTR(name, 1, INSTR(name,',',1,1)-1) AS NameOne,
SUBSTR(name, INSTR(name,',',1,1)+1, LENGTH(name)) AS NameTwo,
SUBSTR(name, 1,INSTR(name,' and ',1,1)-1) AS NameThree,
SUBSTR(name, INSTR(name,' and ',1,1)+1,LENGTH(name)) AS NameFour

但这会创建 4 列。我的目标是拥有 1 个合并列,然后我可以对其进行查询以找到我正在寻找的名称。

【问题讨论】:

  • 首先:在您的帖子中,您说“拆分 AND”(大写字母),但在示例和代码中的任何地方都有“and”(小写字母)。请澄清实际数据中可能存在的内容。第二:您必须小心处理“和”,因为它也可能是名称的一部分。你不想把“Anand Gupta”分成“An”和“Gupta”——对吧?
  • 你有多少个寄存器?我需要知道它,因为我正在考虑收集一些集合来注册您的目标并将其全部放入新表中。但这取决于您的数据量。
  • @mathguy 你们俩都提出了很好的观点,但是这些数据的管理确实很差,所以我只是想为用例做“尽可能好”。只有大约 200 行数据。为了解决“和”问题,我们可以在前后加一个空格。

标签: sql oracle substring


【解决方案1】:

我认为为了拆分名称,最好使用Split_Part Function。用“and”分割时要小心,它可以是名称的一部分。

其次,要处理所有列,您可以使用COALESCE Function

select coalesce (NameOne,NameTwo,NameThree,NameFour)
from (

SELECT SUBSTR(name, 1, INSTR(name,',',1,1)-1) AS NameOne,
SUBSTR(name, INSTR(name,',',1,1)+1, LENGTH(name)) AS NameTwo,
SUBSTR(name, 1,INSTR(name,'and',1,1)-1) AS NameThree,
SUBSTR(name, INSTR(name,'and',1,1)+1,LENGTH(name)) AS NameFour

【讨论】:

    【解决方案2】:

    您可以使用递归子查询因式分解子句来查找分隔符的开始和结束,然后获取这些边界之间的子字符串:

    WITH bounds ( name, start_pos, end_pos, next_pos ) AS (
      SELECT name,
             1,
             REGEXP_INSTR( name, ',\s*|\s+and\s+', 1, 1, 0, 'i' ),
             REGEXP_INSTR( name, ',\s*|\s+and\s+', 1, 1, 1, 'i' )
      FROM   table_name
    UNION ALL
      SELECT name,
             next_pos,
             REGEXP_INSTR( name, ',\s*|\s+and\s+', next_pos, 1, 0, 'i' ),
             REGEXP_INSTR( name, ',\s*|\s+and\s+', next_pos, 1, 1, 'i' )
      FROM   bounds
      WHERE  next_pos > 0
    )
    SEARCH DEPTH FIRST BY name SET rn
    SELECT CASE end_pos
           WHEN 0
           THEN SUBSTR( name, start_pos )
           ELSE SUBSTR( name, start_pos, end_pos - start_pos )
           END As name
    FROM   bounds
    

    其中,对于样本数据:

    CREATE TABLE table_name ( NAME ) AS
    SELECT 'Joe Smith' FROM DUAL UNION ALL
    SELECT 'John Doe and Jane Doe' FROM DUAL UNION ALL
    SELECT 'Jenny May, Steven Thomas' FROM DUAL UNION ALL
    SELECT 'Alice, Beryl, Carol, Debbie, Eva, Frances, Geri, Holly' FROM DUAL;
    

    输出:

    |姓名 | | :------------ | |爱丽丝 | |绿柱石 | |卡罗尔 | |黛比 | |伊娃 | |弗朗西丝 | |杰里 | |冬青 | |珍妮梅 | |史蒂文·托马斯 | |乔·史密斯 | |约翰·多伊 | |简·多伊 |

    db小提琴here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-06
      • 1970-01-01
      相关资源
      最近更新 更多