sql >> Database teknologi >  >> RDS >> Mysql

SQL-forespørgsel returnerer data fra flere tabeller

Del 1 - Sammenslutninger og fagforeninger

Dette svar dækker:

  1. Del 1
    • Samling af to eller flere tabeller ved hjælp af en indre joinforbindelse (se wikipedia-indlægget a> for yderligere oplysninger)
    • Sådan bruger du en fagforeningsforespørgsel
    • Venstre og højre ydre sammenføjninger (dette stackOverflow-svar er fremragende til at beskrive typer af joinforbindelser)
    • Skæringsforespørgsler (og hvordan man gengiver dem, hvis din database ikke understøtter dem) - dette er en funktion af SQL-Server (se info ) og en del af grund til, at jeg skrev det hele i første omgang.
  2. Del 2
    • Underforespørgsler - hvad de er, hvor de kan bruges, og hvad skal man være opmærksom på
    • Cartesian slutter sig til AKA - Åh, elendigheden!

Der er en række måder at hente data fra flere tabeller i en database. I dette svar vil jeg bruge ANSI-92 join-syntaks. Dette kan være anderledes end en række andre tutorials derude, som bruger den ældre ANSI-89 syntaks (og hvis du er vant til 89, kan det virke meget mindre intuitivt - men alt, hvad jeg kan sige er at prøve det), som det er meget nemmere at forstå, når forespørgslerne begynder at blive mere komplekse. Hvorfor bruge det? Er der en præstationsgevinst? Det korte svar er nej, men det er nemmere at læse, når du har vænnet dig til det. Det er lettere at læse forespørgsler skrevet af andre, der bruger denne syntaks.

Jeg vil også bruge konceptet med et lille caryard, som har en database til at holde styr på, hvilke biler den har til rådighed. Ejeren har ansat dig som sin IT-computer og forventer, at du kan aflevere ham de data, han beder om, med det samme.

Jeg har lavet en række opslagstabeller, som skal bruges af finalebordet. Dette vil give os en rimelig model at arbejde ud fra. Til at starte med vil jeg køre mine forespørgsler mod en eksempeldatabase, der har følgende struktur. Jeg vil prøve at tænke på almindelige fejl, der begås, når man starter og forklare, hvad der går galt med dem - samt selvfølgelig vise, hvordan man retter dem.

Den første tabel er simpelthen en farveliste, så vi ved, hvilke farver vi har i bilgården.

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)

Mærketabellen identificerer de forskellige mærker af de biler, som caryard muligvis kan sælge.

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)

Modeltabellen vil dække forskellige typer biler, det bliver nemmere for dette at bruge forskellige biltyper frem for egentlige bilmodeller.

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)

Og til sidst, for at binde alle disse andre borde, bordet der binder alt sammen. ID-feltet er faktisk det unikke partinummer, der bruges til at identificere biler.

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)

Dette vil give os nok data (håber jeg) til at dække nedenstående eksempler på forskellige typer joinforbindelser og også give nok data til at gøre dem umagen værd.

Så når chefen kommer ind i det, vil han gerne vide ID'erne for alle de sportsvogne, han har .

Dette er en simpel sammenføjning med to tabeller. Vi har en tabel, der identificerer modellen og bordet med det tilgængelige lager i. Som du kan se, er dataene i model kolonne af cars tabel relaterer til models kolonne af cars bord vi har. Nu ved vi, at modeltabellen har et ID på 1 til Sports så lad os skrive sammenføjningen.

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

Så denne forespørgsel ser godt ud, ikke? Vi har identificeret de to tabeller og indeholder de oplysninger, vi har brug for, og bruger en joinforbindelse, der korrekt identificerer, hvilke kolonner der skal tilsluttes.

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

Åh nej! En fejl i vores første forespørgsel! Ja, og det er en blomme. Du kan se, forespørgslen har faktisk fået de rigtige kolonner, men nogle af dem findes i begge tabeller, så databasen bliver forvirret over, hvilken kolonne vi mener, og hvor. Der er to løsninger til at løse dette. Den første er fin og enkel, vi kan bruge tableName.columnName at fortælle databasen præcis, hvad vi mener, sådan her:

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)

Den anden bruges nok oftere og kaldes table aliasing. Tabellerne i dette eksempel har fine og korte enkle navne, men skriver noget som KPI_DAILY_SALES_BY_DEPARTMENT ville sandsynligvis hurtigt blive gammel, så en enkel måde er at kalde tabellen sådan her:

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

Nu tilbage til anmodningen. Som du kan se, har vi de oplysninger, vi har brug for, men vi har også oplysninger, der ikke blev bedt om, så vi skal inkludere en hvor-klausul i erklæringen for kun at få de sportsvogne, som blev bedt om. Da jeg foretrækker tabelaliasmetoden frem for at bruge tabelnavnene igen og igen, vil jeg holde mig til den fra dette tidspunkt og fremefter.

Det er klart, at vi skal tilføje en where-klausul til vores forespørgsel. Vi kan identificere sportsvogne enten ved ID=1 eller model='Sports' . Da ID'et er indekseret og den primære nøgle (og det tilfældigvis er mindre skrivning), lad os bruge det i vores forespørgsel.

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! Chefen er glad. Når han er chef og aldrig er tilfreds med det, han bad om, kigger han selvfølgelig på informationen og siger derefter Jeg vil også have farverne .

Okay, så vi har allerede skrevet en god del af vores forespørgsel, men vi skal bruge en tredje tabel, som er farver. Nu, vores vigtigste informationstabel cars gemmer bilens farve-id, og dette linker tilbage til kolonnen for farver-id. Så på samme måde som originalen kan vi slutte os til en tredje tabel:

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)

For fanden, selvom tabellen var korrekt sammenføjet, og de relaterede kolonner var forbundet, glemte vi at hente de faktiske oplysninger fra den nye tabel, som vi lige har linket.

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)

Okay, det er chefen fra vores ryg et øjeblik. For nu at forklare noget af dette lidt mere detaljeret. Som du kan se, er from klausul i vores sætning forbinder vores hovedtabel (jeg bruger ofte en tabel, der indeholder information i stedet for en opslags- eller dimensionstabel. Forespørgslen ville fungere lige så godt med tabellerne skiftet rundt, men giver mindre mening, når vi vender tilbage til denne forespørgsel at læse den om nogle måneder, så det er ofte bedst at prøve at skrive en forespørgsel, der vil være god og nem at forstå - læg den intuitivt ud, brug pæne indrykning, så alt er så tydeligt, som det kan blive. fortsæt med at lære andre, prøv at indgyde disse egenskaber i deres forespørgsler - især hvis du skal fejlfinde dem.

Det er fuldt ud muligt at blive ved med at linke flere og flere tabeller på denne måde.

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

Mens jeg glemte at inkludere en tabel, hvor vi måske ønsker at forbinde mere end én kolonne i join erklæring, her er et eksempel. Hvis models tabellen havde mærkespecifikke modeller og havde derfor også en kolonne kaldet brand som linkede tilbage til brands tabel på ID felt, kunne det gøres som dette:

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

Du kan se, at forespørgslen ovenfor ikke kun linker de sammenføjede tabeller til de vigtigste cars tabel, men angiver også sammenkædninger mellem de allerede sammenføjede tabeller. Hvis dette ikke blev gjort, kaldes resultatet en kartesisk join - hvilket er dba speak for bad. En kartesisk joinforbindelse er en, hvor rækker returneres, fordi oplysningerne ikke fortæller databasen, hvordan resultaterne skal begrænses, så forespørgslen returnerer alle de rækker, der passer til kriterierne.

Så for at give et eksempel på en kartesisk join, lad os køre følgende forespørgsel:

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)

Gode ​​gud, det er grimt. Men hvad databasen angår, er den præcis hvad der blev bedt om. I forespørgslen bad vi om ID fra cars og model fra models . Men fordi vi ikke specificerede hvordan For at deltage i tabellerne har databasen matchet alle række fra den første tabel med hver række fra den anden tabel.

Okay, så chefen er tilbage, og han vil have mere information igen. Jeg vil have den samme liste, men også inkludere 4WD'er i den .

Dette giver os dog en god undskyldning for at se på to forskellige måder at opnå dette på. Vi kunne tilføje en anden betingelse til where-sætningen som denne:

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

Selvom ovenstående vil fungere perfekt, lad os se på det anderledes, dette er en god undskyldning for at vise, hvordan en union forespørgslen vil virke.

Vi ved, at følgende vil returnere alle sportsvognene:

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

Og følgende ville returnere alle 4WD'erne:

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

Så ved at tilføje en union all klausul mellem dem, vil resultaterne af den anden forespørgsel blive tilføjet til resultaterne af den første forespørgsel.

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)

Som du kan se, returneres resultaterne af den første forespørgsel først, efterfulgt af resultaterne af den anden forespørgsel.

I dette eksempel ville det selvfølgelig have været meget nemmere blot at bruge den første forespørgsel, men union forespørgsler kan være gode til specifikke tilfælde. De er en fantastisk måde at returnere specifikke resultater fra tabeller fra tabeller, der ikke nemt kan sættes sammen - eller for den sags skyld helt urelaterede tabeller. Der er dog et par regler, der skal følges.

  • Kolonnetyperne fra den første forespørgsel skal matche kolonnetyperne fra hver anden forespørgsel nedenfor.
  • Navnene på kolonnerne fra den første forespørgsel vil blive brugt til at identificere hele sæt resultater.
  • Antallet af kolonner i hver forespørgsel skal være det samme.

Nu kan du undre dig over, hvad den forskellen er mellem at bruge union og union all . En union forespørgsel vil fjerne dubletter, mens en union all vil ikke. Dette betyder, at der er et lille præstationshit, når du bruger union over union all men resultaterne kan være det værd - jeg vil dog ikke spekulere i den slags i dette.

På denne note kan det være værd at bemærke nogle yderligere noter her.

  • Hvis vi ønskede at bestille resultaterne, kan vi bruge en order by men du kan ikke bruge aliaset længere. I forespørgslen ovenfor, tilføjelse af en order by a.ID ville resultere i en fejl - hvad resultaterne angår, hedder kolonnen ID i stedet for a.ID - selvom det samme alias er blevet brugt i begge forespørgsler.
  • Vi kan kun have én order by sætning, og den skal være som den sidste erklæring.

Til de næste eksempler tilføjer jeg et par ekstra rækker til vores tabeller.

Jeg har tilføjet Holden til mærketabellen. Jeg har også tilføjet en række i cars der har color værdi af 12 - som ikke har nogen reference i farvetabellen.

Okay, chefen er tilbage igen, gøende anmodninger ud - *Jeg vil have en optælling af hvert mærke, vi fører, og antallet af biler i det!` - Typisk kommer vi bare til et interessant afsnit af vores diskussion, og chefen vil have mere arbejde .

Okay, så det første vi skal gøre er at få en komplet liste over mulige mærker.

select
    a.brand
from
    brands a

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

Nu, når vi tilføjer dette til vores biler tabel, får vi følgende resultat:

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)

Hvilket selvfølgelig er et problem - vi kan ikke se nogen omtale af den dejlige Holden mærke, jeg tilføjede.

Dette skyldes, at en join søger efter matchende rækker i begge tabeller. Da der ikke er data i biler, der er af typen Holden det bliver ikke returneret. Det er her, vi kan bruge en outer tilslutte. Dette vil returnere alle resultaterne fra den ene tabel, uanset om de matches i den anden tabel eller ej:

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 hvor vi har det, kan vi tilføje en dejlig aggregeret funktion for at få en optælling og få chefen væk fra ryggen et øjeblik.

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)

Og med det, væk chefen skulker.

For nu at forklare dette mere detaljeret, kan ydre joinforbindelser være til left eller right type. Venstre eller Højre definerer, hvilken tabel der er fuldstændig inkluderet. En left outer join vil inkludere alle rækkerne fra tabellen til venstre, mens (du gættede det) en right outer join bringer alle resultaterne fra tabellen til højre ind i resultaterne.

Nogle databaser tillader en full outer join som vil bringe resultater tilbage (uanset om de matches eller ej) fra begge tabeller, men dette understøttes ikke i alle databaser.

Nu tænker jeg nok på dette tidspunkt, at du spekulerer på, om du kan flette jointyper i en forespørgsel - og svaret er ja, det kan du absolut.

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)

Så hvorfor er det ikke de resultater, der var forventet? Det skyldes, at selvom vi har valgt den ydre sammenføjning fra biler til mærker, var den ikke specificeret i sammenføjningen til farver - så den pågældende sammenføjning vil kun give resultater, der matcher i begge tabeller.

Her er forespørgslen, der ville arbejde for at få de resultater, vi forventede:

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)

Som vi kan se, har vi to ydre joinforbindelser i forespørgslen, og resultaterne kommer igennem som forventet.

Hvad med de andre typer joinforbindelser, spørger du? Hvad med Intersections?

Nå, ikke alle databaser understøtter intersection men stort set alle databaser giver dig mulighed for at skabe et skæringspunkt gennem en joinforbindelse (eller en velstruktureret where-sætning i det mindste).

Et kryds er en type joinforbindelse, der ligner en union som beskrevet ovenfor - men forskellen er, at det kun returnerer rækker af data, der er identiske (og jeg mener identiske) mellem de forskellige individuelle forespørgsler, som fagforeningen tilslutter sig. Kun rækker, der er identiske i enhver henseende, vil blive returneret.

Et simpelt eksempel ville være som sådan:

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

Mens en normal union forespørgsel ville returnere alle rækkerne i tabellen (den første forespørgsel returnerer noget over ID>2 og den anden noget med ID<4 ), hvilket ville resultere i et komplet sæt, ville en skærende forespørgsel kun returnere den række, der matcher id=3 da den opfylder begge kriterier.

Nu, hvis din database ikke understøtter en intersect forespørgsel, kan ovenstående nemt udføres med følgende forespørgsel:

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)

Hvis du ønsker at udføre et kryds på tværs af to forskellige tabeller ved hjælp af en database, der ikke i sagens natur understøtter en krydsningsforespørgsel, skal du oprette en joinforbindelse på hver kolonne af tabellerne.



  1. Fremmednøgle til ikke-primær nøgle

  2. Mens du udfører PITR, ville det være muligt at pause/genoptage i PostgreSQL?

  3. SUM() Funktion i MariaDB

  4. Forklaring af JSONB introduceret af PostgreSQL