दूसरा तरीका होगा -
SELECT housing_id
FROM mytable
WHERE facility_id IN (4,7)
GROUP BY housing_id
HAVING COUNT(DISTINCT facility_id) = 2
अपडेट करें - जोसविक की टिप्पणी से प्रेरित होकर मैंने कुछ और परीक्षण करने का फैसला किया और सोचा कि मैं अपने निष्कर्षों को शामिल करूंगा।
इस क्वेरी का उपयोग करने का एक लाभ यह है कि अधिक सुविधा_आईडी शामिल करने के लिए इसे संशोधित करना आसान है। अगर आप उन सभी हाउसिंग_आईड्स को ढूंढना चाहते हैं जिनमें फैसिलिटी_आईड्स 1, 3, 4 और 7 हैं तो आप बस -
SELECT housing_id
FROM mytable
WHERE facility_id IN (1,3,4,7)
GROUP BY housing_id
HAVING COUNT(DISTINCT facility_id) = 4
इन तीनों प्रश्नों का प्रदर्शन नियोजित अनुक्रमण रणनीति के आधार पर बहुत भिन्न होता है। मैं अपने परीक्षण डेटासेट पर, निर्भर सबक्वेरी संस्करण से उचित प्रदर्शन प्राप्त करने में असमर्थ था, भले ही इंडेक्सिंग का उपयोग किया गया हो।
टिम द्वारा प्रदान किया गया सेल्फ जॉइन समाधान दो कॉलमों पर दिए गए अलग-अलग सिंगल कॉलम इंडेक्स को बहुत अच्छा प्रदर्शन करता है, लेकिन मानदंड की संख्या बढ़ने के साथ-साथ बहुत अच्छा प्रदर्शन नहीं करता है।
यहां मेरी परीक्षण तालिका पर कुछ बुनियादी आंकड़े दिए गए हैं - 500k पंक्तियां - 147963 Housing_ids 1 और 9 के बीच सुविधा_आईडी के संभावित मानों के साथ।
इन सभी परीक्षणों को चलाने के लिए उपयोग किए जाने वाले सूचकांक यहां दिए गए हैं -
SHOW INDEXES FROM mytable;
+---------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type |
+---------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+
| mytable | 0 | UQ_housing_facility | 1 | housing_id | A | 500537 | NULL | NULL | | BTREE |
| mytable | 0 | UQ_housing_facility | 2 | facility_id | A | 500537 | NULL | NULL | | BTREE |
| mytable | 0 | UQ_facility_housing | 1 | facility_id | A | 12 | NULL | NULL | | BTREE |
| mytable | 0 | UQ_facility_housing | 2 | housing_id | A | 500537 | NULL | NULL | | BTREE |
| mytable | 1 | IX_housing | 1 | housing_id | A | 500537 | NULL | NULL | | BTREE |
| mytable | 1 | IX_facility | 1 | facility_id | A | 12 | NULL | NULL | | BTREE |
+---------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+
परीक्षण की गई पहली क्वेरी निर्भर सबक्वेरी है -
SELECT SQL_NO_CACHE DISTINCT housing_id
FROM mytable
WHERE housing_id IN (SELECT housing_id FROM mytable WHERE facility_id=4)
AND housing_id IN (SELECT housing_id FROM mytable WHERE facility_id=7);
17321 rows in set (9.15 sec)
+----+--------------------+---------+-----------------+----------------------------------------------------------------+---------------------+---------+------------+--------+---------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+---------+-----------------+----------------------------------------------------------------+---------------------+---------+------------+--------+---------------------------------------+
| 1 | PRIMARY | mytable | range | NULL | IX_housing | 4 | NULL | 500538 | Using where; Using index for group-by |
| 3 | DEPENDENT SUBQUERY | mytable | unique_subquery | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | UQ_housing_facility | 8 | func,const | 1 | Using index; Using where |
| 2 | DEPENDENT SUBQUERY | mytable | unique_subquery | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | UQ_housing_facility | 8 | func,const | 1 | Using index; Using where |
+----+--------------------+---------+-----------------+----------------------------------------------------------------+---------------------+---------+------------+--------+---------------------------------------+
SELECT SQL_NO_CACHE DISTINCT housing_id
FROM mytable
WHERE housing_id IN (SELECT housing_id FROM mytable WHERE facility_id=1)
AND housing_id IN (SELECT housing_id FROM mytable WHERE facility_id=3)
AND housing_id IN (SELECT housing_id FROM mytable WHERE facility_id=4)
AND housing_id IN (SELECT housing_id FROM mytable WHERE facility_id=7);
567 rows in set (9.30 sec)
+----+--------------------+---------+-----------------+----------------------------------------------------------------+---------------------+---------+------------+--------+---------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+---------+-----------------+----------------------------------------------------------------+---------------------+---------+------------+--------+---------------------------------------+
| 1 | PRIMARY | mytable | range | NULL | IX_housing | 4 | NULL | 500538 | Using where; Using index for group-by |
| 5 | DEPENDENT SUBQUERY | mytable | unique_subquery | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | UQ_housing_facility | 8 | func,const | 1 | Using index; Using where |
| 4 | DEPENDENT SUBQUERY | mytable | unique_subquery | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | UQ_housing_facility | 8 | func,const | 1 | Using index; Using where |
| 3 | DEPENDENT SUBQUERY | mytable | unique_subquery | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | UQ_housing_facility | 8 | func,const | 1 | Using index; Using where |
| 2 | DEPENDENT SUBQUERY | mytable | unique_subquery | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | UQ_housing_facility | 8 | func,const | 1 | Using index; Using where |
+----+--------------------+---------+-----------------+----------------------------------------------------------------+---------------------+---------+------------+--------+---------------------------------------+
अगला मेरा संस्करण है जो GROUP BY का उपयोग कर रहा है ... HAVING COUNT ...
SELECT SQL_NO_CACHE housing_id
FROM mytable
WHERE facility_id IN (4,7)
GROUP BY housing_id
HAVING COUNT(DISTINCT facility_id) = 2;
17321 rows in set (0.79 sec)
+----+-------------+---------+-------+---------------------------------+-------------+---------+------+--------+------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------------------------+-------------+---------+------+--------+------------------------------------------+
| 1 | SIMPLE | mytable | range | UQ_facility_housing,IX_facility | IX_facility | 4 | NULL | 198646 | Using where; Using index; Using filesort |
+----+-------------+---------+-------+---------------------------------+-------------+---------+------+--------+------------------------------------------+
SELECT SQL_NO_CACHE housing_id
FROM mytable
WHERE facility_id IN (1,3,4,7)
GROUP BY housing_id
HAVING COUNT(DISTINCT facility_id) = 4;
567 rows in set (1.25 sec)
+----+-------------+---------+-------+---------------------------------+-------------+---------+------+--------+------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------------------------+-------------+---------+------+--------+------------------------------------------+
| 1 | SIMPLE | mytable | range | UQ_facility_housing,IX_facility | IX_facility | 4 | NULL | 407160 | Using where; Using index; Using filesort |
+----+-------------+---------+-------+---------------------------------+-------------+---------+------+--------+------------------------------------------+
और अंतिम लेकिन कम से कम स्वयं शामिल हों -
SELECT SQL_NO_CACHE a.housing_id
FROM mytable a
INNER JOIN mytable b
ON a.housing_id = b.housing_id
WHERE a.facility_id = 4 AND b.facility_id = 7;
17321 rows in set (1.37 sec)
+----+-------------+-------+--------+----------------------------------------------------------------+---------------------+---------+-------------------------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+----------------------------------------------------------------+---------------------+---------+-------------------------+-------+-------------+
| 1 | SIMPLE | b | ref | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | IX_facility | 4 | const | 94598 | Using index |
| 1 | SIMPLE | a | eq_ref | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | UQ_housing_facility | 8 | test.b.housing_id,const | 1 | Using index |
+----+-------------+-------+--------+----------------------------------------------------------------+---------------------+---------+-------------------------+-------+-------------+
SELECT SQL_NO_CACHE a.housing_id
FROM mytable a
INNER JOIN mytable b
ON a.housing_id = b.housing_id
INNER JOIN mytable c
ON a.housing_id = c.housing_id
INNER JOIN mytable d
ON a.housing_id = d.housing_id
WHERE a.facility_id = 1
AND b.facility_id = 3
AND c.facility_id = 4
AND d.facility_id = 7;
567 rows in set (1.64 sec)
+----+-------------+-------+--------+----------------------------------------------------------------+---------------------+---------+-------------------------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+----------------------------------------------------------------+---------------------+---------+-------------------------+-------+--------------------------+
| 1 | SIMPLE | b | ref | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | IX_facility | 4 | const | 93782 | Using index |
| 1 | SIMPLE | d | eq_ref | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | UQ_housing_facility | 8 | test.b.housing_id,const | 1 | Using index |
| 1 | SIMPLE | c | eq_ref | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | UQ_housing_facility | 8 | test.b.housing_id,const | 1 | Using index |
| 1 | SIMPLE | a | eq_ref | UQ_housing_facility,UQ_facility_housing,IX_housing,IX_facility | UQ_housing_facility | 8 | test.d.housing_id,const | 1 | Using where; Using index |
+----+-------------+-------+--------+----------------------------------------------------------------+---------------------+---------+-------------------------+-------+--------------------------+