【问题标题】:Look for text in one field contained in another field Oracle SQL在另一个字段中包含的一个字段中查找文本 Oracle SQL
【发布时间】:2014-07-02 19:43:20
【问题描述】:

如果有人问过这个问题,我深表歉意,我无法用语言表达。

我被要求过滤掉一个字段中的文本包含在另一个字段中的查询中的行。一个例子可能会更好地解释它:

    Column_1         Column_2
    Low Static       Static
    Static           Static
    Static           Clear
                     Static
    Very Low Freq    Freq

查询的结果应该只返回第 3 行和第 4 行,因为第 1、2 和 5 行包含相似的字符串。现在,我有以下情况:

    WHERE
    ((Column_2 NOT LIKE '%' || Column_1 || '%')
    OR (Column_1 NOT LIKE '%' || Column_2 || '%' OR Column_1 IS NULL))

但是,当我只想返回第 3 行和第 4 行时,它会返回第 1、3、4 和 5 行。这只是示例数据,我的实际数据集在第 1 列和第 2 列中包含许多不同的文本字符串,所以我可以'不只是编写特定的案例语句来排除列相似的某些实例。

也许这是不可能的,因为我无法将字符串定义为包含在 2 个空格内的内容,同时考虑到没有空格的情况?

谢谢

【问题讨论】:

  • 将第一个或更改为和WHERE (column_2 not like '%' || column_1 || '%' and column_1 not like '%' || column_2 || '%') OR Column_1 is null OR column_2 is null
  • 问题的标题与问题的后半部分相反,您说“我只想返回第 3 行和第 4 行”,所以我很困惑。
  • 感谢您的发现。我将其更改为 AND 修复了一些情况,但我仍然得到不一致的结果,例如第 1 列 = 'Right Sound Noise' 和第 2 列 = 'Sound Noise Clear' (所以我想排除该行)。
  • “在一个字段中查找包含在另一个字段中的文本...然后排除符合条件的行”。我希望这会有所帮助。

标签: sql oracle text sql-like


【解决方案1】:

对于你的表达,我想你想要and而不是or

WHERE ((Column_2 NOT LIKE '%' || Column_1 || '%') AND
       (Column_1 NOT LIKE '%' || Column_2 || '%' OR Column_1 IS NULL)
      )

您需要满足这两个条件。您可能会发现逻辑更容易遵循:

WHERE NOT (Column_2 LIKE '%' || Column_1 || '%' OR
           Column_1 LIKE '%' || Column_2 || '%'
          )

【讨论】:

    【解决方案2】:

    您要使用的方法是进行全表扫描,因此它不会随着表的增长而扩展。如果您想实现更高效的解决方案(不使用 Oracle 大文本索引),使用索引,请使用基于函数的索引来预先计算列的公共子字符串。

    使用 INSTR() 可以找出一列是否是另一列的子字符串,并返回一个分数。 0 表示不匹配。

    create index ix_t_score on t (instr(nvl(column_1,' '), nvl(column_2, ' ')),
                                  instr(nvl(column_2,' '), nvl(column_1, ' ')));
    

    现在编写查询,使其允许 Oracle 使用索引。

    -- Find rows that don't have common strings
    select * from t
      where instr(nvl(column_1, ' '), nvl(column_2, ' ')) = 0 and
            instr(nvl(column_2, ' '), nvl(column_1, ' ')) = 0;
    
    -- Find rows that do
    select * from t
      where instr(nvl(column_1, ' '), nvl(column_2, ' ')) > 0 or
            instr(nvl(column_2, ' '), nvl(column_1, ' ')) > 0;
    
    
    set autotrace on
    
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 4100696360
    
    ---------------------------------------------------------------------------------
    | Id  | Operation         | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |             |     1 |    22 |     2   (0)| 00:00:01 |
    |   1 |  SORT AGGREGATE   |             |     1 |    22 |            |          |
    |*  2 |   INDEX RANGE SCAN| IX_T_SCORE  |     1 |    22 |     2   (0)| 00:00:01 |
    ---------------------------------------------------------------------------------
    
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access(INSTR(NVL("COLUMN_1",' '),NVL("COLUMN_2",' '))=0 AND
                  INSTR(NVL("COLUMN_2",' '),NVL("COLUMN_1",' '))=0)
    

    你可以通过创建一个确定性的存储过程/函数来返回一个分数来简化它,并且SQL变得比上面的简单得多。 NVL() 的用途是处理带有空值的列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-15
      • 2020-06-25
      • 1970-01-01
      • 2015-09-23
      • 1970-01-01
      • 2021-11-09
      • 2023-03-07
      相关资源
      最近更新 更多