I have a product filter based on data from multiple tables.
I make query using IN 2 and more times in one query. This works great and only selects products that have
- and needed attributes
- and needed options
- and needed categories
SELECT COUNT(*) FROM `test_oc_product`
WHERE product_id IN (
SELECT product_id
FROM test_oc_product_option
WHERE option_id = '21' AND value = 'Red'
)
AND product_id IN (
SELECT product_id
FROM test_oc_product_attribute
WHERE attribute_id = '10'
)
Also I found INTERSECT operator. But there are some nuances
— works ok
(SELECT product_id FROM `test_oc_product`)
INTERSECT
(SELECT product_id
FROM test_oc_product_attribute
WHERE attribute_id = '10')
INTERSECT
(SELECT product_id
FROM test_oc_product_option
WHERE option_id = '21'
AND value = 'Red')
— doesn’t work
(SELECT * FROM `test_oc_product`)
INTERSECT
(SELECT product_id
FROM test_oc_product_attribute
WHERE attribute_id = '10'
)
INTERSECT
(SELECT product_id
FROM test_oc_product_option
WHERE option_id = '21' AND value = 'Red'
)
— doesn’t work
(SELECT COUNT(*) FROM `test_oc_product`)
INTERSECT
(SELECT product_id
FROM test_oc_product_attribute
WHERE attribute_id = '10'
)
INTERSECT
(SELECT product_id
FROM test_oc_product_option
WHERE option_id = '21' AND value = 'Red'
)
I not found such examples with IN operator on the Internet. Is it OK to use IN 2 or more times in one sql-query?
I need to select only those products that match the given parameters. And these parameters are stored in different tables
There is a dump with some tables in an abbreviated form
CREATE TABLE test_oc_product (
product_id int(11) NOT NULL AUTO_INCREMENT,
model varchar(64) NOT NULL,
sku varchar(64) NOT NULL,
PRIMARY KEY (product_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO test_oc_product (product_id, model, sku) VALUES
(1, 'A1', 'A1'),
(2, 'A2', 'A2'),
(3, 'A3', 'A3'),
(4, 'AA', 'AA'),
(5, 'A5', 'A5'),
(6, 'A6', 'A6'),
(7, 'A7', 'A7'),
(8, 'A8', 'A8');
CREATE TABLE test_oc_product_attribute (
product_id int(11) NOT NULL,
attribute_id int(11) NOT NULL,
text text NOT NULL,
PRIMARY KEY (product_id, attribute_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO test_oc_product_attribute (product_id, attribute_id, text) VALUES
('1', '10', 'Attribute Value 1'),
('2', '11', 'Attribute Value 2');
CREATE TABLE test_oc_product_option (
product_option_id int(11) NOT NULL AUTO_INCREMENT,
product_id int(11) NOT NULL,
option_id int(11) NOT NULL,
value text NOT NULL,
PRIMARY KEY (product_option_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO test_oc_product_option (product_option_id, product_id, option_id, value) VALUES
(NULL, '1', '21', 'Red'),
(NULL, '2', '21', 'Red'),
(NULL, '3', '21', 'Blue'),
(NULL, '4', '10', 'S');
2
Answers
As I mentioned in the comments, you need the same number of columns to use intersect.
Why not try using JOIN instead like this:
NOTE
Kudos to @TimBiegeleisen for noticing and provided a fix
There is nothing wrong per se in using
IN
more than once in the same query. For reference, I would probably use your first version, refactored to useEXISTS
instead ofIN
:For performance, the following two indices should speed up the two exists subqueries: