sql >> Database >  >> RDS >> Mysql

SQL-query retourneert gegevens uit meerdere tabellen

Deel 1 - Toetredingen en vakbonden

Dit antwoord omvat:

  1. Deel 1
  2. Deel 2
    • Subquery's - wat ze zijn, waar ze kunnen worden gebruikt en waar je op moet letten
    • Cartesian sluit zich aan bij AKA - Oh, de ellende!

Er zijn een aantal manieren om gegevens uit meerdere tabellen in een database op te halen. In dit antwoord zal ik de syntaxis van ANSI-92 gebruiken. Dit kan verschillen van een aantal andere tutorials die de oudere ANSI-89-syntaxis gebruiken (en als je gewend bent aan 89, lijkt het misschien veel minder intuïtief - maar alles wat ik kan zeggen is om het te proberen) zoals het is veel gemakkelijker te begrijpen wanneer de vragen complexer worden. Waarom het gebruiken? Is er prestatiewinst? Het korte antwoord is nee, maar het is is leest makkelijker als je er eenmaal aan gewend bent. Het is gemakkelijker om zoekopdrachten te lezen die zijn geschreven door andere mensen die deze syntaxis gebruiken.

Ik ga ook het concept van een kleine garage gebruiken die een database heeft om bij te houden welke auto's beschikbaar zijn. De eigenaar heeft je ingehuurd als zijn IT-computerman en verwacht dat je hem in een mum van tijd de gegevens kunt bezorgen waar hij om vraagt.

Ik heb een aantal opzoektabellen gemaakt die door de finaletafel zullen worden gebruikt. Dit geeft ons een redelijk model om vanuit te werken. Om te beginnen zal ik mijn query's uitvoeren op een voorbeelddatabase met de volgende structuur. Ik zal proberen veelgemaakte fouten te bedenken die bij het begin worden gemaakt en uit te leggen wat er mis gaat - en natuurlijk ook laten zien hoe ze te corrigeren.

De eerste tabel is gewoon een kleurenlijst, zodat we weten welke kleuren we in de autostalling hebben.

mysql> create table colors(id int(3) not null auto_increment primary key, 
    -> color varchar(15), paint varchar(10));
Query OK, 0 rows affected (0.01 sec)

mysql> show columns from colors;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(3)      | NO   | PRI | NULL    | auto_increment |
| color | varchar(15) | YES  |     | NULL    |                |
| paint | varchar(10) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

mysql> insert into colors (color, paint) values ('Red', 'Metallic'), 
    -> ('Green', 'Gloss'), ('Blue', 'Metallic'), 
    -> ('White' 'Gloss'), ('Black' 'Gloss');
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> select * from colors;
+----+-------+----------+
| id | color | paint    |
+----+-------+----------+
|  1 | Red   | Metallic |
|  2 | Green | Gloss    |
|  3 | Blue  | Metallic |
|  4 | White | Gloss    |
|  5 | Black | Gloss    |
+----+-------+----------+
5 rows in set (0.00 sec)

De merkentabel identificeert de verschillende merken van de auto's die de garage mogelijk zou kunnen verkopen.

mysql> create table brands (id int(3) not null auto_increment primary key, 
    -> brand varchar(15));
Query OK, 0 rows affected (0.01 sec)

mysql> show columns from brands;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(3)      | NO   | PRI | NULL    | auto_increment |
| brand | varchar(15) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)

mysql> insert into brands (brand) values ('Ford'), ('Toyota'), 
    -> ('Nissan'), ('Smart'), ('BMW');
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> select * from brands;
+----+--------+
| id | brand  |
+----+--------+
|  1 | Ford   |
|  2 | Toyota |
|  3 | Nissan |
|  4 | Smart  |
|  5 | BMW    |
+----+--------+
5 rows in set (0.00 sec)

De modeltabel zal betrekking hebben op verschillende soorten auto's, het wordt hierdoor eenvoudiger om verschillende autotypes te gebruiken in plaats van echte automodellen.

mysql> create table models (id int(3) not null auto_increment primary key, 
    -> model varchar(15));
Query OK, 0 rows affected (0.01 sec)

mysql> show columns from models;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(3)      | NO   | PRI | NULL    | auto_increment |
| model | varchar(15) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> insert into models (model) values ('Sports'), ('Sedan'), ('4WD'), ('Luxury');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from models;
+----+--------+
| id | model  |
+----+--------+
|  1 | Sports |
|  2 | Sedan  |
|  3 | 4WD    |
|  4 | Luxury |
+----+--------+
4 rows in set (0.00 sec)

En tot slot, om al die andere tafels aan elkaar te knopen, de tafel die alles samenbindt. Het ID-veld is eigenlijk het unieke lotnummer dat wordt gebruikt om auto's te identificeren.

mysql> create table cars (id int(3) not null auto_increment primary key, 
    -> color int(3), brand int(3), model int(3));
Query OK, 0 rows affected (0.01 sec)

mysql> show columns from cars;
+-------+--------+------+-----+---------+----------------+
| Field | Type   | Null | Key | Default | Extra          |
+-------+--------+------+-----+---------+----------------+
| id    | int(3) | NO   | PRI | NULL    | auto_increment |
| color | int(3) | YES  |     | NULL    |                |
| brand | int(3) | YES  |     | NULL    |                |
| model | int(3) | YES  |     | NULL    |                |
+-------+--------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql> insert into cars (color, brand, model) values (1,2,1), (3,1,2), (5,3,1), 
    -> (4,4,2), (2,2,3), (3,5,4), (4,1,3), (2,2,1), (5,2,3), (4,5,1);
Query OK, 10 rows affected (0.00 sec)
Records: 10  Duplicates: 0  Warnings: 0

mysql> select * from cars;
+----+-------+-------+-------+
| id | color | brand | model |
+----+-------+-------+-------+
|  1 |     1 |     2 |     1 |
|  2 |     3 |     1 |     2 |
|  3 |     5 |     3 |     1 |
|  4 |     4 |     4 |     2 |
|  5 |     2 |     2 |     3 |
|  6 |     3 |     5 |     4 |
|  7 |     4 |     1 |     3 |
|  8 |     2 |     2 |     1 |
|  9 |     5 |     2 |     3 |
| 10 |     4 |     5 |     1 |
+----+-------+-------+-------+
10 rows in set (0.00 sec)

Dit geeft ons genoeg gegevens (hoop ik) om de onderstaande voorbeelden van verschillende soorten joins te verdoezelen en ook genoeg gegevens om ze de moeite waard te maken.

Dus om er helemaal in te gaan, wil de baas weten De ID's van alle sportwagens die hij heeft .

Dit is een eenvoudige join met twee tabellen. We hebben een tabel die het model identificeert en de tafel met de beschikbare voorraad erin. Zoals u kunt zien, zijn de gegevens in het model kolom van de cars tabel heeft betrekking op de models kolom van de cars tafel die we hebben. Nu weten we dat de modellentabel een ID heeft van 1 voor Sports dus laten we de join schrijven.

select
    ID,
    model
from
    cars
        join models
            on model=ID

Dus deze query ziet er goed uit toch? We hebben de twee tabellen geïdentificeerd en bevatten de informatie die we nodig hebben en gebruiken een join die correct identificeert aan welke kolommen we moeten deelnemen.

ERROR 1052 (23000): Column 'ID' in field list is ambiguous

Oh nee! Een fout in onze eerste zoekopdracht! Ja, en het is een pruim. De query heeft inderdaad de juiste kolommen, maar sommige staan ​​in beide tabellen, dus de database raakt in de war over welke kolom we bedoelen en waar. Er zijn twee oplossingen om dit op te lossen. De eerste is leuk en eenvoudig, we kunnen tableName.columnName . gebruiken om de database precies te vertellen wat we bedoelen, als volgt:

select
    cars.ID,
    models.model
from
    cars
        join models
            on cars.model=models.ID

+----+--------+
| ID | model  |
+----+--------+
|  1 | Sports |
|  3 | Sports |
|  8 | Sports |
| 10 | Sports |
|  2 | Sedan  |
|  4 | Sedan  |
|  5 | 4WD    |
|  7 | 4WD    |
|  9 | 4WD    |
|  6 | Luxury |
+----+--------+
10 rows in set (0.00 sec)

De andere wordt waarschijnlijk vaker gebruikt en wordt tabelaliasing genoemd. De tabellen in dit voorbeeld hebben mooie en korte eenvoudige namen, maar typ iets als KPI_DAILY_SALES_BY_DEPARTMENT zou waarschijnlijk snel oud worden, dus een eenvoudige manier is om de tafel als volgt een bijnaam te geven:

select
    a.ID,
    b.model
from
    cars a
        join models b
            on a.model=b.ID

Nu terug naar het verzoek. Zoals je kunt zien, hebben we de informatie die we nodig hebben, maar we hebben ook informatie waar niet om is gevraagd, dus we moeten een waar-clausule in de verklaring opnemen om alleen de sportwagens te krijgen zoals gevraagd. Omdat ik de voorkeur geef aan de tabelaliasmethode in plaats van de tabelnamen steeds opnieuw te gebruiken, zal ik me er vanaf dit punt aan houden.

Het is duidelijk dat we een waar-clausule aan onze query moeten toevoegen. We kunnen sportwagens identificeren aan de hand van ID=1 of model='Sports' . Omdat de ID is geïndexeerd en de primaire sleutel (en het is minder typen), laten we die gebruiken in onze zoekopdracht.

select
    a.ID,
    b.model
from
    cars a
        join models b
            on a.model=b.ID
where
    b.ID=1

+----+--------+
| ID | model  |
+----+--------+
|  1 | Sports |
|  3 | Sports |
|  8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)

Bingo! De baas is blij. Natuurlijk, als baas en nooit tevreden met wat hij vroeg, kijkt hij naar de informatie en zegt dan Ik wil ook de kleuren .

Oké, dus we hebben een groot deel van onze query al geschreven, maar we moeten een derde tabel gebruiken die kleuren is. Nu, onze hoofdinformatietabel cars slaat de kleur-ID van de auto op en deze linkt terug naar de kolom met de kleuren-ID. Dus, op een gelijkaardige manier als het origineel, kunnen we deelnemen aan een derde tafel:

select
    a.ID,
    b.model
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
where
    b.ID=1

+----+--------+
| ID | model  |
+----+--------+
|  1 | Sports |
|  3 | Sports |
|  8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)

Verdorie, hoewel de tabel correct was samengevoegd en de gerelateerde kolommen waren gekoppeld, waren we vergeten de daadwerkelijke informatie in te voeren uit de nieuwe tabel die we zojuist hebben gekoppeld.

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
where
    b.ID=1

+----+--------+-------+
| ID | model  | color |
+----+--------+-------+
|  1 | Sports | Red   |
|  8 | Sports | Green |
| 10 | Sports | White |
|  3 | Sports | Black |
+----+--------+-------+
4 rows in set (0.00 sec)

Juist, dat is even de baas van ons af. Nu, om het een en ander in meer detail uit te leggen. Zoals je kunt zien, is de from clausule in onze verklaring verbindt onze hoofdtabel (ik gebruik vaak een tabel die informatie bevat in plaats van een opzoek- of dimensietabel. De query zou net zo goed werken als de tabellen allemaal omgedraaid zijn, maar heeft minder zin als we terugkomen op deze query om het in een paar maanden te lezen, dus het is vaak het beste om te proberen een vraag te schrijven die leuk en gemakkelijk te begrijpen is - leg het intuïtief uit, gebruik mooie inspringingen zodat alles zo duidelijk mogelijk is. ga door met het onderwijzen van anderen, probeer deze kenmerken in hun vragen in te voeren - vooral als je ze gaat oplossen.

Het is heel goed mogelijk om op deze manier steeds meer tabellen te blijven koppelen.

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=1

Hoewel ik vergat een tabel op te nemen waarin we mogelijk meer dan één kolom willen toevoegen in de join verklaring, hier is een voorbeeld. Als de models tabel had merkspecifieke modellen en had daarom ook een kolom met de naam brand die terug linkten naar de brands tabel op de ID veld, kan het als volgt worden gedaan:

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
            and b.brand=d.ID
where
    b.ID=1

U kunt zien dat de bovenstaande zoekopdracht niet alleen de samengevoegde tabellen koppelt aan de belangrijkste cars table, maar specificeert ook joins tussen de reeds samengevoegde tabellen. Als dit niet is gebeurd, wordt het resultaat een cartesiaanse join genoemd - wat een slechte zaak is. Een cartesiaanse join is er een waarbij rijen worden geretourneerd omdat de informatie de database niet vertelt hoe de resultaten moeten worden beperkt, dus de query retourneert alle de rijen die aan de criteria voldoen.

Dus, om een ​​voorbeeld te geven van een cartesiaanse join, laten we de volgende query uitvoeren:

select
    a.ID,
    b.model
from
    cars a
        join models b

+----+--------+
| ID | model  |
+----+--------+
|  1 | Sports |
|  1 | Sedan  |
|  1 | 4WD    |
|  1 | Luxury |
|  2 | Sports |
|  2 | Sedan  |
|  2 | 4WD    |
|  2 | Luxury |
|  3 | Sports |
|  3 | Sedan  |
|  3 | 4WD    |
|  3 | Luxury |
|  4 | Sports |
|  4 | Sedan  |
|  4 | 4WD    |
|  4 | Luxury |
|  5 | Sports |
|  5 | Sedan  |
|  5 | 4WD    |
|  5 | Luxury |
|  6 | Sports |
|  6 | Sedan  |
|  6 | 4WD    |
|  6 | Luxury |
|  7 | Sports |
|  7 | Sedan  |
|  7 | 4WD    |
|  7 | Luxury |
|  8 | Sports |
|  8 | Sedan  |
|  8 | 4WD    |
|  8 | Luxury |
|  9 | Sports |
|  9 | Sedan  |
|  9 | 4WD    |
|  9 | Luxury |
| 10 | Sports |
| 10 | Sedan  |
| 10 | 4WD    |
| 10 | Luxury |
+----+--------+
40 rows in set (0.00 sec)

Goeie god, dat is lelijk. Wat de database betreft, is het echter precies waar werd om gevraagd. In de zoekopdracht hebben we gevraagd om de ID van cars en het model van models . Omdat we echter niet hebben gespecificeerd hoe om de tabellen samen te voegen, heeft de database elke rij vanaf de eerste tafel met elke rij van de tweede tafel.

Oké, dus de baas is terug en hij wil weer meer informatie. Ik wil dezelfde lijst, maar er ook 4WD's in opnemen .

Dit geeft ons echter een goed excuus om naar twee verschillende manieren te kijken om dit te bereiken. We zouden een andere voorwaarde kunnen toevoegen aan de waar-clausule als volgt:

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=1
    or b.ID=3

Hoewel het bovenstaande perfect zal werken, laten we het anders bekijken, is dit een geweldig excuus om te laten zien hoe een union query zal werken.

We weten dat het volgende alle sportwagens zal teruggeven:

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=1

En het volgende zou alle 4WD's retourneren:

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=3

Dus door een union all . toe te voegen clausule ertussen, worden de resultaten van de tweede zoekopdracht toegevoegd aan de resultaten van de eerste zoekopdracht.

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=1
union all
select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=3

+----+--------+-------+
| ID | model  | color |
+----+--------+-------+
|  1 | Sports | Red   |
|  8 | Sports | Green |
| 10 | Sports | White |
|  3 | Sports | Black |
|  5 | 4WD    | Green |
|  7 | 4WD    | White |
|  9 | 4WD    | Black |
+----+--------+-------+
7 rows in set (0.00 sec)

Zoals u kunt zien, worden eerst de resultaten van de eerste zoekopdracht geretourneerd, gevolgd door de resultaten van de tweede zoekopdracht.

In dit voorbeeld was het natuurlijk veel gemakkelijker geweest om gewoon de eerste zoekopdracht te gebruiken, maar union query's kunnen geweldig zijn voor specifieke gevallen. Ze zijn een geweldige manier om specifieke resultaten te retourneren van tabellen van tabellen die niet gemakkelijk aan elkaar te koppelen zijn - of wat dat betreft volledig niet-gerelateerde tabellen. Er zijn echter een paar regels die u moet volgen.

  • De kolomtypen van de eerste zoekopdracht moeten overeenkomen met de kolomtypen van elke andere zoekopdracht hieronder.
  • De namen van de kolommen uit de eerste zoekopdracht worden gebruikt om de volledige reeks resultaten te identificeren.
  • Het aantal kolommen in elke zoekopdracht moet hetzelfde zijn.

Nu vraag je je misschien de verschil is tussen het gebruik van union en union all . Een union query zal duplicaten verwijderen, terwijl een union all zal niet. Dit betekent wel dat er een kleine prestatiehit is bij het gebruik van union over union all maar de resultaten zijn misschien de moeite waard - ik zal hier echter niet over speculeren.

Bij deze opmerking is het misschien de moeite waard om hier enkele aanvullende opmerkingen te maken.

  • Als we de resultaten willen bestellen, kunnen we een order by . gebruiken maar je kunt de alias niet meer gebruiken. Voeg in de bovenstaande zoekopdracht een order by a.ID zou resulteren in een fout - wat de resultaten betreft, heet de kolom ID in plaats van a.ID - ook al is in beide zoekopdrachten dezelfde alias gebruikt.
  • We kunnen slechts één order by verklaring, en het moet als de laatste verklaring zijn.

Voor de volgende voorbeelden voeg ik een paar extra rijen toe aan onze tabellen.

Ik heb Holden toegevoegd aan de merkentabel. Ik heb ook een rij toegevoegd aan cars die de color . heeft waarde van 12 - die geen verwijzing heeft in de kleurentabel.

Oké, de baas is weer terug, blaffende verzoeken - *Ik wil een telling van elk merk dat we voeren en het aantal auto's erin!' - Typisch, we komen gewoon bij een interessant deel van onze discussie en de baas wil meer werk .

Juist, dus het eerste dat we moeten doen, is een volledige lijst van mogelijke merken krijgen.

select
    a.brand
from
    brands a

+--------+
| brand  |
+--------+
| Ford   |
| Toyota |
| Nissan |
| Smart  |
| BMW    |
| Holden |
+--------+
6 rows in set (0.00 sec)

Als we dit nu samenvoegen met onze autotabel, krijgen we het volgende resultaat:

select
    a.brand
from
    brands a
        join cars b
            on a.ID=b.brand
group by
    a.brand

+--------+
| brand  |
+--------+
| BMW    |
| Ford   |
| Nissan |
| Smart  |
| Toyota |
+--------+
5 rows in set (0.00 sec)

Wat natuurlijk een probleem is - we zien geen enkele vermelding van de mooie Holden merk dat ik heb toegevoegd.

Dit komt omdat een join zoekt naar overeenkomende rijen in beide tafels. Aangezien er geen gegevens zijn in auto's van het type Holden het wordt niet geretourneerd. Hier kunnen we een outer . gebruiken meedoen. Hiermee wordt alle geretourneerd de resultaten van de ene tabel, of ze nu overeenkomen in de andere tabel of niet:

select
    a.brand
from
    brands a
        left outer join cars b
            on a.ID=b.brand
group by
    a.brand

+--------+
| brand  |
+--------+
| BMW    |
| Ford   |
| Holden |
| Nissan |
| Smart  |
| Toyota |
+--------+
6 rows in set (0.00 sec)

Nu we dat hebben, kunnen we een mooie aggregatiefunctie toevoegen om een ​​telling te krijgen en de baas even van ons af te zetten.

select
    a.brand,
    count(b.id) as countOfBrand
from
    brands a
        left outer join cars b
            on a.ID=b.brand
group by
    a.brand

+--------+--------------+
| brand  | countOfBrand |
+--------+--------------+
| BMW    |            2 |
| Ford   |            2 |
| Holden |            0 |
| Nissan |            1 |
| Smart  |            1 |
| Toyota |            5 |
+--------+--------------+
6 rows in set (0.00 sec)

En daarmee sluipt de baas weg.

Om dit wat meer in detail uit te leggen, kunnen outer joins van de left . zijn of right type. Links of Rechts bepaalt welke tafel volledig is inbegrepen. Een left outer join zal alle rijen uit de tabel aan de linkerkant bevatten, terwijl (je raadt het al) een right outer join brengt alle resultaten uit de tabel aan de rechterkant in de resultaten.

Sommige databases staan ​​een full outer join toe die resultaten oplevert (al dan niet overeenkomend) van beide tabellen, maar dit wordt niet in alle databases ondersteund.

Nu, ik denk dat je je op dit moment waarschijnlijk afvraagt ​​of je join-types in een query kunt samenvoegen - en het antwoord is ja, dat kan absoluut.

select
    b.brand,
    c.color,
    count(a.id) as countOfBrand
from
    cars a
        right outer join brands b
            on b.ID=a.brand
        join colors c
            on a.color=c.ID
group by
    a.brand,
    c.color

+--------+-------+--------------+
| brand  | color | countOfBrand |
+--------+-------+--------------+
| Ford   | Blue  |            1 |
| Ford   | White |            1 |
| Toyota | Black |            1 |
| Toyota | Green |            2 |
| Toyota | Red   |            1 |
| Nissan | Black |            1 |
| Smart  | White |            1 |
| BMW    | Blue  |            1 |
| BMW    | White |            1 |
+--------+-------+--------------+
9 rows in set (0.00 sec)

Dus waarom zijn dat niet de verwachte resultaten? De reden is dat, hoewel we de buitenste join van auto's tot merken hebben geselecteerd, deze niet is gespecificeerd in de join met kleuren - dus die bepaalde join levert alleen resultaten op die in beide tabellen overeenkomen.

Hier is de query die zou werken om de resultaten te krijgen die we verwachtten:

select
    a.brand,
    c.color,
    count(b.id) as countOfBrand
from
    brands a
        left outer join cars b
            on a.ID=b.brand
        left outer join colors c
            on b.color=c.ID
group by
    a.brand,
    c.color

+--------+-------+--------------+
| brand  | color | countOfBrand |
+--------+-------+--------------+
| BMW    | Blue  |            1 |
| BMW    | White |            1 |
| Ford   | Blue  |            1 |
| Ford   | White |            1 |
| Holden | NULL  |            0 |
| Nissan | Black |            1 |
| Smart  | White |            1 |
| Toyota | NULL  |            1 |
| Toyota | Black |            1 |
| Toyota | Green |            2 |
| Toyota | Red   |            1 |
+--------+-------+--------------+
11 rows in set (0.00 sec)

Zoals we kunnen zien, hebben we twee outer joins in de query en de resultaten komen door zoals verwacht.

Hoe zit het met die andere soorten joins die je vraagt? Hoe zit het met kruispunten?

Welnu, niet alle databases ondersteunen het intersection maar in vrijwel alle databases kun je een kruising maken via een join (of op zijn minst een goed gestructureerd waar-statement).

Een Intersection is een type join dat enigszins lijkt op een union zoals hierboven beschreven - maar het verschil is dat het alleen retourneert rijen met gegevens die identiek zijn (en ik bedoel identiek) tussen de verschillende individuele query's die door de unie zijn samengevoegd. Alleen rijen die in elk opzicht identiek zijn, worden geretourneerd.

Een eenvoudig voorbeeld zou als volgt zijn:

select
    *
from
    colors
where
    ID>2
intersect
select
    *
from
    colors
where
    id<4

Terwijl een normale union query retourneert alle rijen van de tabel (de eerste query retourneert iets meer dan ID>2 en de tweede alles met ID<4 ) wat zou resulteren in een volledige set, zou een intersect-query alleen de rij retourneren die overeenkomt met id=3 omdat het aan beide criteria voldoet.

Als uw database nu geen intersect ondersteunt, vraag, kan het bovenstaande eenvoudig worden bereikt met de volgende vraag:

select
    a.ID,
    a.color,
    a.paint
from
    colors a
        join colors b
            on a.ID=b.ID
where
    a.ID>2
    and b.ID<4

+----+-------+----------+
| ID | color | paint    |
+----+-------+----------+
|  3 | Blue  | Metallic |
+----+-------+----------+
1 row in set (0.00 sec)

Als u een intersectie wilt uitvoeren over twee verschillende tabellen met behulp van een database die niet inherent een intersectiequery ondersteunt, moet u een join maken op elke kolom van de tafels.



  1. Hoe kan ik een primaire sleutel maken als AUTOINCREMENT

  2. Hoe we databases gebruiken in ons dagelijks leven

  3. Hoe de Oracle-functie in Python aan te roepen?

  4. VMware CPU Hot Plug vNUMA-effecten op SQL Server