简体   繁体   中英

How can I use AND condition using array parameter in a query

I have an oracle query that has several parameter, one of the parameter is like an array, the parameter name for example :COLOR. let say I have a table PEOPLE

 ID    NAME   WARECOLOR
 12   Sabrina   red
 12   Sabrina   blue
 32   Mark      blue
 45   Bob       red 
 25   Lean      white
 01   Sara      Orange

I want to use this parameter in two way in two different queries, one using the OR condition and the other one using the AND condition. let say I want all the names who have "Red OR blue" If I send the parameter into :COLORS to be as

|red|blue|

and write this query

SELECT ID, NAME, COLOR
FROM PEOPLE
WHERE  INSTR(:COLORS, COLORS) > 0
GROUP ID, NAME, COLOR;

The result will be like:

 ID    NAME   WARECOLOR
 12   Sabrina   red
 12   Sabrina   blue
 32   Mark      blue
 45   Bob       red 

which is good, but my question is: how can I use it to be AND condition? Like if I want all the names who have "Red AND blue", which means the result should be like:

 ID    NAME   WARECOLOR
 12   Sabrina   red
 12   Sabrina   blue

could any one help me through this case please?

To find the persons, you can:

SELECT ID, NAME
FROM PEOPLE
WHERE  INSTR(:COLORS, WARECOLOR) > 0
GROUP ID, NAME
HAVING COUNT(*) = regexp_count(:COLORS,'[|]') - 1 ;

regexp_count(:COLORS,'[|]') just counts the | from :COLORS. If your table is not properly normalized(you have duplicates) you may use count(distinct WARECOLOR) instead of count(*)

Then it is simple to get the rows:

SELECT ID, NAME, COLOR
FROM PEOPLE
WHERE  id, name in (
    SELECT ID, NAME
    FROM PEOPLE
    WHERE  INSTR(:COLORS, WARECOLOR) > 0
    GROUP ID, NAME
    HAVING COUNT(*) = regexp_count(:COLORS,'[|]') - 1 ;
 )
;

You can try below SQL script on your SQL Server development environment. I used the user defined function dbo.split() to split input string using SQL

/*create table colorTbl (
ID int,   NAME   varchar(10), WARECOLOR varchar(10)
)
insert into colorTbl select 12,'Sabrina','red'
insert into colorTbl select 12   ,'Sabrina','blue'
insert into colorTbl select  32   ,'Mark','blue'
insert into colorTbl select  45   ,'Bob','red' 
insert into colorTbl select  25   ,'Lean','white'
insert into colorTbl select  01   ,'Sara','Orange'*/

declare @color varchar(max) = '|red|blue|'

;with cte as (
    select val, COUNT(*) over (partition by 1) cnt1
    from dbo.Split(@color,'|')
    where val <> ''
)
select * 
from (
select *, COUNT(*) over (partition by name) cnt2
from colorTbl c
inner join cte on c.warecolor = cte.val
) t where cnt1 = cnt2

The split function returns colors and order number of each color. This enables you to know the count of the input parameters. Using SQL Count() function with Partition By clause enables me count rows with colors matched for each user. When I match these two count values, you will implement AND for concatenated parameter values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM