简体   繁体   中英

Sql select where array in column

In my query I use join table category_attributes . Let's assume we have such rows:

category_id|attribute_id
1|1
1|2
1|3

I want to have the query which suites the two following needs. I have a variable (php) of allowed attribute_id's . If the array is subset of attribute_id then category_id should be selected, if not - no results.

First case:

select * from category_attributes where (1,2,3,4) in category_attributes.attribute_id

should give no results.

Second case

select * from category_attributes where (1,2,3) in category_attributes.attribute_id

should give all three rows (see dummy rows at the beginning).

So I would like to have reverse side of what standard SQL in does.

Solution

Step 1: Group the data by the field you want to check.

Step 2: Left join the list of required values with the records obtained in the previous step.

Step 3: Now we have a list with required values and corresponding values from the table. The second column will be equal to required value if it exist in the table and NULL otherwise.

步骤 3 输出

Count null values in the right column. If it is equal to 0, then it means table contains all the required values. In that case return all records from the table. Otherwise there must be at least one required value is missing in the table. So, return no records.


Sample

Table "Data":

表数据

Required values:
10, 20, 50

Query:

SELECT * 
FROM   Data 
WHERE  (SELECT Count(*) 
        FROM   (SELECT D.value 
                FROM   (SELECT 10 AS value 
                        UNION 
                        SELECT 20 AS value 
                        UNION 
                        SELECT 50 AS value) T 
                       LEFT JOIN (SELECT value 
                                  FROM   Data 
                                  GROUP  BY value) D 
                              ON ( T.value = D.value )) J 
        WHERE  value IS NULL) = 0;

You can use group by and having :

select ca.category_id
from category_attributes ca
where ca.attribute_id in (1, 2, 3, 4) 
group by ca.category_id
having count(*) = 4;  -- "4" is the size of the list

This assumes that the table has no duplicates (which is typical for attribute mapping tables). If that is a possibility, use:

having count(distinct ca.attribute_id) = 4

You can aggregate attribute_id into array and compare two array from php.

SELECT category_id FROM 
(select category_id, group_concat(attribute_id) as attributes from category_attributes
order by attribute_id) t WHERE t.attributes = (1, 2, 3);

But you need to find another way to compare arrays or make sure that array is always sorted.

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