En anden tilgang ville være -
VÆLG bolig_idFRA mintabel WHERE facility_id IN (4,7)GROUP BY housing_idHAVING COUNT(DISTINCT facility_id) =2
OPDATERING - inspireret af kommentaren fra Josvic besluttede jeg mig for at lave nogle flere tests og tænkte, at jeg ville inkludere mine resultater.
En af fordelene ved at bruge denne forespørgsel er, at den er let at ændre for at inkludere flere facility_ids. Hvis du vil finde alle bolig_id'er, der har facilitets_id 1, 3, 4 og 7, gør du bare -
VÆLG bolig_idFRA mintabel HVOR facilitets_id IN (1,3,4,7)GRUPPER EFTER bolig_id, DER HAR ANTAL(DISTINCT facilitets_id) =4
Ydeevnen for alle tre af disse forespørgsler varierer meget baseret på den anvendte indekseringsstrategi. Jeg var ikke i stand til at få en rimelig ydeevne på mit testdatasæt fra den afhængige underforespørgselsversion uanset den anvendte indeksering.
Selvkoblingsløsningen leveret af Tim klarer sig meget godt givet separate enkeltkolonneindekser på de to kolonner, men klarer sig ikke helt så godt, da antallet af kriterier stiger.
Her er nogle grundlæggende statistikker på min testtabel - 500.000 rækker - 147963 bolig-id'er med potentielle værdier for facility_id mellem 1 og 9.
Her er de indekser, der bruges til at køre alle disse tests -
VIS INDEKSER FRA mytabel;+---------+------+-------- ------+---------------+-------------+------------- -------------------+--------+-------------- -+| Tabel | Ikke_unik | Nøglenavn | Seq_in_index | Kolonne_navn | Samling | Kardinalitet | Underdel | Pakket | Nul | Indekstype |+---------+-----------------------------+--- --------------+-------------+---------------- --+----------+--------+------+------------+| mytabel | 0 | UQ_boliganlæg | 1 | bolig_id | A | 500537 | NULL | NULL | | BTREE || mytabel | 0 | UQ_boliganlæg | 2 | facility_id | A | 500537 | NULL | NULL | | BTREE || mytabel | 0 | UQ_facility_housing | 1 | facility_id | A | 12 | NULL | NULL | | BTREE || mytabel | 0 | UQ_facility_housing | 2 | bolig_id | A | 500537 | NULL | NULL | | BTREE || mytabel | 1 | IX_bolig | 1 | bolig_id | A | 500537 | NULL | NULL | | BTREE || mytabel | 1 | IX_facilitet | 1 | facility_id | A | 12 | NULL | NULL | | BTREE |+--------------------------- --------------+-------------+---------------- --+----------+--------+------+------------+
Den første testede forespørgsel er den afhængige underforespørgsel -
SELECT SQL_NO_CACHE DISTINCT housing_idFROM mytableWHERE 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 | vælg_type | bord | type | mulige_nøgler | nøgle | key_len | ref | rækker | Ekstra |+----+---------------------+--------+----------- ------+--------------------------------------------------- ----------------------+----------------------+------ ---+------------+--------+------------------------ ---------------+| 1 | PRIMÆR | mytabel | rækkevidde | NULL | IX_bolig | 4 | NULL | 500538 | Brug af hvor; Brug af indeks til gruppe-efter || 3 | AFHÆNGIG UNDERSØGNING | mytabel | unik_underforespørgsel | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | UQ_boliganlæg | 8 | func,const | 1 | Brug af indeks; Bruger hvor || 2 | AFHÆNGIG UNDERSØGNING | mytabel | unik_underforespørgsel | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | UQ_boliganlæg | 8 | func,const | 1 | Brug af indeks; Bruger hvor |+----+----------------------+--------+---------- -------+-------------------------------------------------- ----------------------+---------------------+----- ----+------------+--------+----------------------- ----------------+SELECT SQL_NO_CACHE DISTINCT housing_idFROM mytableWHERE 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 rækker i sæt (9,30 sek.)+----+------------ ----+---------+-----------------+------------- -------------------------------------------------- --+--------------------------------------- -----+----------------------------------------------+| id | vælg_type | bord | type | mulige_nøgler | nøgle | key_len | ref | rækker | Ekstra |+----+---------------------+--------+----------- ------+--------------------------------------------------- ----------------------+----------------------+------ ---+------------+--------+------------------------ ---------------+| 1 | PRIMÆR | mytabel | rækkevidde | NULL | IX_bolig | 4 | NULL | 500538 | Brug af hvor; Brug af indeks til gruppe-efter || 5 | AFHÆNGIG UNDERSØGNING | mytabel | unik_underforespørgsel | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | UQ_boliganlæg | 8 | func,const | 1 | Brug af indeks; Bruger hvor || 4 | AFHÆNGIG UNDERSØGNING | mytabel | unik_underforespørgsel | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | UQ_boliganlæg | 8 | func,const | 1 | Brug af indeks; Bruger hvor || 3 | AFHÆNGIG UNDERSØGNING | mytabel | unik_underforespørgsel | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | UQ_boliganlæg | 8 | func,const | 1 | Brug af indeks; Bruger hvor || 2 | AFHÆNGIG UNDERSØGNING | mytabel | unik_underforespørgsel | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | UQ_boliganlæg | 8 | func,const | 1 | Brug af indeks; Bruger hvor |+----+----------------------+--------+---------- -------+-------------------------------------------------- ----------------------+---------------------+----- ----+------------+--------+----------------------- ----------------+
Dernæst er min version, der bruger GRUPPER AF ... AT HA COUNT ...
SELECT SQL_NO_CACHE housing_idFROM mytableWHERE facility_id IN (4,7)GROUP BY housing_idHAVING COUNT(DISTINCT facility_id) =2;17321 rows in set (0,79 sek)+----+-------- -----+---------+-------+-------------------------------- -------+-------------+--------+------+--------+-- ------------------------------------------+| id | vælg_type | bord | type | mulige_nøgler | nøgle | key_len | ref | rækker | Ekstra |+----+-------------+--------+-------+-------- -----------------------+-------------+--------+-- ----+--------+-------------------------------------------- ------+| 1 | ENKELT | mytabel | rækkevidde | UQ_facility_housing,IX_facility | IX_facilitet | 4 | NULL | 198646 | Brug af hvor; Brug af indeks; Brug af filersortering |+----+-------------+--------+--------+-------- --------------------+-------------+---------+- -----+--------+------------------------------------ -------+VÆLG SQL_NO_CACHE bolig_idFRA mintabel HVOR facilitets_id IN (1,3,4,7)GRUPPE EFTER bolig_id, DER HAR ANTAL(DISTINCT facilitets_id) =4;567 rækker i sæt (1,25 sek.)+----+-- --------------------------------------------- --------------+--------------+--------+------+----- ---+--------------------------------------------------+| id | vælg_type | bord | type | mulige_nøgler | nøgle | key_len | ref | rækker | Ekstra |+----+-------------+--------+-------+-------- -----------------------+-------------+--------+-- ----+--------+-------------------------------------------- ------+| 1 | ENKELT | mytabel | rækkevidde | UQ_facility_housing,IX_facility | IX_facilitet | 4 | NULL | 407160 | Brug af hvor; Brug af indeks; Brug af filersortering |+----+-------------+--------+--------+-------- --------------------+-------------+---------+- -----+--------+------------------------------------ -------+
Og sidst men ikke mindst er selvet med -
SELECT SQL_NO_CACHE a.housing_idFROM mytable aINNER JOIN mytable b PÅ a.housing_id =b.housing_idWHERE a.facility_id =4 OG b.facility_id =7;17321 rækker i sæt (1,37 sek.)+---+ --------------+--------+--------+------------------------ ----------------------------------------------+---- ------------------+---------+---------------------- ---+--------+-------------+| id | vælg_type | bord | type | mulige_nøgler | nøgle | key_len | ref | rækker | Ekstra |+----+-------------+-------+--------+----- -------------------------------------------------- ---+---------------------+-----------+-------- ---------------+-------------+| 1 | ENKELT | b | ref | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | IX_facilitet | 4 | konst | 94598 | Brug af indeks || 1 | ENKELT | en | eq_ref | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | UQ_boliganlæg | 8 | test.b.housing_id,const | 1 | Brug af indeks |+----+-------------+-------+--------+---------- -------------------------------------------------- ----+----------------------------+------------- --------------+-------+-------------+SELECT SQL_NO_CACHE a.housing_idFROM mytable aINNER JOIN mytable b PÅ a.housing_id =b.housing_idINNER JOIN mytable c ON a.housing_id =c.housing_idINNER JOIN mytable d ON a.housing_id =d.housing_idWHERE a.facility_id =1AND b.facility_id =3AND c.facility_id =4AND 7; (1,64 sek.)+----+-------------+-------+--------+-------- -------------------------------------------------- -----+----------------------+----------+------- --------------+-------+--------------------------+| id | vælg_type | bord | type | mulige_nøgler | nøgle | key_len | ref | rækker | Ekstra |+----+-------------+-------+--------+----- -------------------------------------------------- ---+---------------------+-----------+-------- ---------------+-------------------------+| 1 | ENKELT | b | ref | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | IX_facilitet | 4 | konst | 93782 | Brug af indeks || 1 | ENKELT | d | eq_ref | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | UQ_boliganlæg | 8 | test.b.housing_id,const | 1 | Brug af indeks || 1 | ENKELT | c | eq_ref | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | UQ_boliganlæg | 8 | test.b.housing_id,const | 1 | Brug af indeks || 1 | ENKELT | en | eq_ref | UQ_bolig_facilitet,UQ_facilitet_boliger,IX_bolig,IX_facilitet | UQ_boliganlæg | 8 | test.d.housing_id,const | 1 | Brug af hvor; Brug af indeks |+----+-------------+-------+--------+---------- -------------------------------------------------- ----+---------------------+----------+------- --------------+-------+--------------------------------+