【问题标题】:how to use split function in both the side of condition in oracle如何在oracle的条件两侧使用拆分功能
【发布时间】:2016-11-09 15:01:34
【问题描述】:

嗨,我有一个表格,其中的值如下所示

    user_country
    -------------
    210|9|211
    210|211
    9|87
    210|117|54

我有一个分割函数,它用字符“|”分割数据. 当用户输入像 210|9 这样的值时 应返回包含 210 和 9 值的列(即应仅返回第 1 行)。 我尝试了多个存在但无法得到实际答案

到目前为止尝试过:

    SELECT 1
    FROM TABLE(split_text_fn('210|9', '|')) a
    WHERE EXISTS
       (SELECT 1
          FROM TABLE(split_text_fn('210|87', '|')) b
         WHERE     b.COLUMN_VALUE = a.COLUMN_VALUE
               AND EXISTS
                       (SELECT 1
                          FROM TABLE(split_text_fn('210|9', '|')) a1
                         WHERE a1.COLUMN_VALUE = b.COLUMN_VALUE))

【问题讨论】:

  • 请发布您尝试过的代码。
  • 你会考虑标准化你的数据库模型吗?同一列中的多个数据不是一个好习惯。
  • 另外,请发布该数据所需的结果
  • 从表中选择 1(split_text_fn('210|9','|'))a 存在于哪里(从表中选择 1(split_text_fn('210|87','|'))b 在哪里b.column_value = a.column_value 并且存在(从表中选择 1(split_text_fn('210|9','|'))a1 WHERE a1.column_value = b.column_value))
  • @manikandan 编辑问题并添加查询,不要在 cmets 向我们扔。

标签: oracle exists split-function


【解决方案1】:

我不完全确定我是否理解,但是...假设您的函数将采用管道分隔的字符串并将其拆分为它包含的多个标记,并假设用户输入一个管道分隔的字符串作为绑定变量:input,您的基表是 table_1,其中有一列 user_country 可能还有其他列,并且您希望在 table_1 中找到所有行,其中 user_country 包含来自 :input 的所有标记:

select * 
from   table_1
where not exists ( select column_value from table(split_text_fn(:input, '|')) 
                   minus 
                   select column_value from table(split_text_fn(user_country))
                 )
;

这可能会花费很多时间 - 违反第一范式所付出的代价。您可以拥有良好的性能,或者您可以在这种非常糟糕的设计中拥有数据,但不能两者兼而有之。

【讨论】:

    【解决方案2】:

    如果我理解正确的话,我认为你在追求类似的东西:

    WITH your_table AS (SELECT 1 user_id, '210|9|211' user_country FROM dual UNION ALL
                        SELECT 2 user_id, '210|211' user_country FROM dual UNION ALL
                        SELECT 3 user_id, '9|87' user_country FROM dual UNION ALL
                        SELECT 4 user_id, '210|117|54' user_country FROM dual),
    -- end of mimicking a table containing your data; you wouldn't need the above subquery
    -- as you would just select directly from your table instead
      vals_to_check AS (SELECT regexp_substr(:p_values_to_check_for, '[^'||:p_delimiter||']+', 1, LEVEL) val,
                               COUNT(DISTINCT regexp_substr(:p_values_to_check_for, '[^'||:p_delimiter||']+', 1, LEVEL)) OVER () cnt_vals
                        FROM   dual
                        CONNECT BY regexp_substr(:p_values_to_check_for, '[^'||:p_delimiter||']+', 1, LEVEL) IS NOT NULL)
    SELECT yt.user_id,
           yt.user_country
    FROM   your_table yt
           INNER JOIN vals_to_check vtc ON :p_delimiter||yt.user_country||:p_delimiter LIKE '%'||:p_delimiter||vtc.val||:p_delimiter||'%'
    GROUP BY yt.user_id,
             yt.user_country,
             vtc.cnt_vals
    HAVING   COUNT(*) = cnt_vals;
    

    结果:

    -- with the bind variables set to the following:
    variable p_delimiter varchar2
    variable p_values_to_check_for varchar2
    exec :p_delimiter := '|'; :p_values_to_check_for := '210|9';
    
       USER_ID USER_COUNTRY
    ---------- ------------
             1 210|9|211
    
    -- with the bind variables set to the following:
    variable p_delimiter varchar2
    variable p_values_to_check_for varchar2
    exec :p_delimiter := '|'; :p_values_to_check_for := '210|211';
    
       USER_ID USER_COUNTRY
    ---------- ------------
             1 210|9|211
             2 210|211
    

    注意我直接在 sql 中对输入字符串进行了拆分——不需要单独的 pl/sql 函数调用。但是,您可能希望继续使用您的 split_text_fn 函数,在这种情况下,您可以跳过声明 vals_to_check 子查询,而只需在主 SQL 语句中使用您的 table(split_text_fn(...))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-08
      • 2012-03-19
      • 1970-01-01
      • 2020-07-31
      相关资源
      最近更新 更多