在oracle 12中搜索逗号分隔值

时间:2017-07-19 07:12:10

标签: sql oracle plsql

我有一个表 - Product在Oracle中,其中p_spc_cat_id以逗号分隔值存储。

p_id p_name p_desc p_spc_cat_id
1    AA     AAAA   26,119,27,15,18
2    BB     BBBB   0,0,27,56,57,4
3    BB     CCCC   26,0,0,15,3,8
4    CC     DDDD   26,0,27,7,14,10
5    CC     EEEE   26,119,0,48,75

现在我要搜索p_namep_spc_cat_id '26,119,7'的{​​{1}}并且此搜索值不固定,有时会'7,27,8'。搜索文本组合每次都会更改

我的查询是:

select p_id,p_name from product where p_spc_cat_id in('26,119,7');

当我执行此查询时,我无法找到任何结果

6 个答案:

答案 0 :(得分:1)

我回答的时间不多,但我希望我能正确理解这个问题。

在以下情况下进一步阅读:您有一个存储

等记录的表格
1. 10,20,30,40
2. 50,40,20,70
3. 80,60,30,40

和#10; 10,60'之类的搜索字符串,在这种情况下它应返回第1行和第1行。 3。

请尝试以下,它适用于我的小桌子&数据

create table Temp_Table_Name (some_id number(6), Ab varchar2(100))
insert into Temp_Table_Name values (1,'112,120')
insert into Temp_Table_Name values (2,'7,8,100,26')

首先让我们分解逻辑:

  • 该表在其中一列[Column AB]中包含逗号分隔数据。
  • 我们有一个逗号分隔的字符串,我们需要在该字符串列中单独搜索。 [' 26,119,7,18' -X_STRING]
  • ID列是表中的主键。

1。)让表格中的每条记录多次x次,其中x是搜索字符串[X_STRING]中逗号分隔值的计数。我们可以使用下面的查询来创建笛卡尔连接子查询表。

Select Rownum Sequencer,'26,119,7,18' X_STRING 
from dual 
CONNECT BY ROWNUM <= (LENGTH( '26,119,7,18') - LENGTH(REPLACE( '26,119,7,18',',',''))) + 1

小记:计算逗号分隔值的计数=

Length of string - length of string without ',' + 1 [add one for last value]

2。)创建一个PARSING_STRING函数,使PARSING_STRING(字符串,位置)。所以,如果我通过:

PARSING_STRING('26,119,7,18',3) it should return 7.

CREATE OR REPLACE Function PARSING_STRING
(String_Inside IN Varchar2, Position_No IN Number) 
Return Varchar2 Is
    OurEnd   Number; Beginn Number;
Begin

    If Position_No < 1 Then 
    Return Null; 
    End If;

    OurEnd := Instr(String_Inside, ',', 1, Position_No);

    If OurEnd = 0 Then
        OurEnd := Length(String_Inside) + 1;
    End If;

    If Position_No = 1 Then
        Beginn := 1;
    Else
        Beginn := Instr(String_Inside, ',', 1, Position_No-1) + 1;
    End If;

    Return Substr(String_Inside, Beginn, OurEnd-Beginn);

End;
/

3。)主查询,使用连接来乘以记录。:

select t1.*,PARSING_STRING(X_STRING,Sequencer) 
from Temp_Table_Name t1,
(Select Rownum Sequencer,'26,119,7,18' X_STRING from dual 
CONNECT BY ROWNUM <= (Select (LENGTH( '26,119,7,18') - LENGTH(REPLACE( 
'26,119,7,18',',',''))) + 1 from dual))  t2

请注意,对于每个相乘的记录,我们从逗号分隔的字符串中获取1个特定的位置值。

4。)完成where条件:

Where
/* For when the value is in the middle of the strint [,value,] */
AB like '%,'||PARSING_STRING(X_STRING,Sequencer)||',%'
OR
/* For when the value is in the start of the string [value,] 
parsing the first position comma separated value to match*/
PARSING_STRING(AB,1) = PARSING_STRING(X_STRING,Sequencer)
OR
/* For when the value is in the end of the string [,value] 
parsing the last position comma separated value to match*/
PARSING_STRING(AB,(LENGTH(AB) - LENGTH(REPLACE(AB,',',''))) + 1) = 
PARSING_STRING(X_STRING,Sequencer)

5.在查询中使用distinct来获取唯一ID

[最终查询:上述所有逻辑的组合:1查询全部查找]

select distinct Some_ID
from Temp_Table_Name t1,
(Select Rownum Sequencer,'26,119,7,18' X_STRING from dual 
CONNECT BY ROWNUM <= (Select (LENGTH( '26,119,7,18') - LENGTH(REPLACE( '26,119,7,18',',',''))) + 1 from dual))  t2
Where
AB like '%,'||PARSING_STRING(X_STRING,Sequencer)||',%'
OR
PARSING_STRING(AB,1) = PARSING_STRING(X_STRING,Sequencer)
OR
PARSING_STRING(AB,(LENGTH(AB) - LENGTH(REPLACE(AB,',',''))) + 1) = PARSING_STRING(X_STRING,Sequencer)

答案 1 :(得分:0)

您可以使用喜欢找到它:

select p_id,p_name from product where p_spc_cat_id like '%26,119%'
or p_spc_cat_id like '%119,26%' or p_spc_cat_id like '%119,%,26%' or p_spc_cat_id like '%26,%,119%';

答案 2 :(得分:0)

SELECT p_id,p_name
FROM product
WHERE p_spc_cat_id
LIKE '%'||'&i_str'||'%'`      

其中i_str26,119,77,27,8

答案 3 :(得分:0)

使用Oracle函数instr()来实现您的目标。在你的情况下:

SELECT p_name 
FROM product 
WHERE instr(p_spc_cat_id, '26,119') <> 0;

Oracle Doc for INSTR

答案 4 :(得分:0)

如果您要搜索的字符串总是有3个值(即存在2个逗号),那么您可以使用以下方法。

    where  p_spc_cat_id like regexp_substr('your_search_string, '[^,]+', 1, 1) 
or p_spc_cat_id like regexp_substr('your_search_string', '[^,]+', 1, 2) 
or p_spc_cat_id like regexp_substr('your_search_string', '[^,]+', 1, 3)

如果您无法预测搜索字符串中有多少值 (在多少逗号中)你可能需要生成动态查询。

不幸的是,sql fiddle目前无法正常工作,因此无法测试此代码。

答案 5 :(得分:0)

此解决方案使用CTE。 “产品”构建主表。 “product_split”将产品转换为行,因此p_spc_cat_id中的每个元素都在其自己的行中。最后,在product_split中搜索字符串'26,119,7'中的每个值,该值由connect by转换为行。

with product(p_id, p_name, p_desc, p_spc_cat_id) as (
  select 1, 'AA', 'AAAA', '26,119,27,15,18' from dual union all
  select 2, 'BB', 'BBBB', '0,0,27,56,57,4'  from dual union all
  select 3, 'BB', 'CCCC', '26,0,0,15,3,8'   from dual union all
  select 4, 'CC', 'DDDD', '26,0,27,7,14,10' from dual union all
  select 5, 'CC', 'EEEE', '26,119,0,48,75'  from dual
),
product_split(p_id, p_name, p_spc_cat_id) as (
  select p_id, p_name, 
         regexp_substr(p_spc_cat_id, '(.*?)(,|$)', 1, level, NULL, 1)
  from product
  connect by level <= regexp_count(p_spc_cat_id, ',')+1   
    and prior p_id = p_id
    and prior sys_guid() is not null 
)
-- select * from product_split;
select distinct p_id, p_name
from product_split
where p_spc_cat_id in(
  select regexp_substr('26,119,7', '(.*?)(,|$)', 1, level, NULL, 1) from dual
  connect by level <= regexp_count('26,119,7', ',') + 1
)
order by p_id;

      P_ID P_
---------- --
         1 AA
         3 BB
         4 CC
         5 CC

SQL>