Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Kueri SQL melalui beberapa baris

Pendekatan lain adalah -

SELECT housing_id
FROM mytable
WHERE facility_id IN (4,7)
GROUP BY housing_id
HAVING COUNT(DISTINCT facility_id) = 2

PERBARUI - terinspirasi oleh komentar Josvic, saya memutuskan untuk melakukan beberapa pengujian lagi dan berpikir saya akan memasukkan temuan saya.

Salah satu keuntungan menggunakan kueri ini adalah mudah dimodifikasi untuk menyertakan lebih banyak fasilitas_id. Jika Anda ingin menemukan semua housing_id yang memiliki fasilitas_id 1, 3, 4 &7, cukup lakukan -

SELECT housing_id
FROM mytable
WHERE facility_id IN (1,3,4,7)
GROUP BY housing_id
HAVING COUNT(DISTINCT facility_id) = 4

Kinerja ketiga kueri ini sangat bervariasi berdasarkan strategi pengindeksan yang digunakan. Saya tidak bisa mendapatkan kinerja yang wajar, pada dataset pengujian saya, dari versi subquery dependen terlepas dari pengindeksan yang digunakan.

Solusi self-join yang disediakan oleh Tim berkinerja sangat baik dengan indeks kolom tunggal yang terpisah pada dua kolom, tetapi tidak bekerja dengan baik karena jumlah kriteria meningkat.

Berikut adalah beberapa statistik dasar pada tabel pengujian saya - 500 ribu baris - 147963 housing_id dengan nilai potensial untuk fasilitas_id antara 1 dan 9.

Berikut adalah indeks yang digunakan untuk menjalankan semua pengujian ini -

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      |
+---------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+

Kueri pertama yang diuji adalah subkueri dependen -

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              |
+----+--------------------+---------+-----------------+----------------------------------------------------------------+---------------------+---------+------------+--------+---------------------------------------+

Selanjutnya versi saya menggunakan 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 |
+----+-------------+---------+-------+---------------------------------+-------------+---------+------+--------+------------------------------------------+

Dan yang tak kalah pentingnya adalah bergabung sendiri -

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 |
+----+-------------+-------+--------+----------------------------------------------------------------+---------------------+---------+-------------------------+-------+--------------------------+


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara mengulang fungsi tersimpan di MySQL dengan benar?

  2. Java - Mendapatkan Data dari database MySQL

  3. Ubah bahasa pesan kesalahan MySQL

  4. Masalah Python:Tidak dapat menemukan vcvarsall.bat

  5. Bisakah sebuah atribut menunjuk satu tabel di atas yang lain?