sql >> Databasteknik >  >> RDS >> PostgreSQL

Skapar en fråga som returnerar id om villkoret matchas i rader från två tabeller

Har läst din fråga på Meta om just den här frågan, låt mig förklara varför alla tre svaren verkligen är korrekta - liksom hur du utarbetade det.

Jag har inkluderat exempel på alla tre svaren och schemat som de arbetar med:

Database changed
mysql> create table carpet(id int(3), material varchar(10), color varchar(15));
Query OK, 0 rows affected (0.02 sec)

mysql> create table curtain(id int(3), material varchar(10), color varchar(15));
Query OK, 0 rows affected (0.00 sec)

(en massa infoga uttalanden)

mysql> select * from carpet;
+------+-----------+--------------+
| id   | material  | color        |
+------+-----------+--------------+
|    1 | wool      | Light Yellow |
|    2 | wool      | Beige        |
|    3 | polyester | Light Yellow |
|    4 | polyester | Light Red    |
+------+-----------+--------------+
4 rows in set (0.00 sec)

mysql> select * from curtain;
+------+----------+--------------+
| id   | material | color        |
+------+----------+--------------+
|    1 | Velvet   | Purple       |
|    2 | cotton   | White        |
|    3 | cotton   | Light Yellow |
|    4 | cotton   | Light Blue   |
+------+----------+--------------+
4 rows in set (0.00 sec)

En skärning använder två urvalssatser och ger matchande resultat. I det här fallet letar du efter alla rader som har en matchande färg "Ljusgul".

Jag kan inte ge dig ett exempel i MySQL eftersom det inte stöder det (Som du kan se nedan behövs det inte för att ge samma resultat).

En unionsfråga med två utvalda satser var och en med en where-sats som endast tillåter färgen "Ljusgul" kommer att returnera samma data. Även om en union kan användas för att returnera data som inte stämmer överens, betyder where-satsen i varje select-sats att den faktiskt bara returnerar de rader du vill ha.

mysql> select id, material, color from carpet
    -> union 
    -> select id, material, color from curtain;
+------+-----------+--------------+
| id   | material  | color        |
+------+-----------+--------------+
|    1 | wool      | Light Yellow |
|    2 | wool      | Beige        |
|    3 | polyester | Light Yellow |
|    4 | polyester | Light Red    |
|    1 | Velvet    | Purple       |
|    2 | cotton    | White        |
|    3 | cotton    | Light Yellow |
|    4 | cotton    | Light Blue   |
+------+-----------+--------------+
8 rows in set (0.00 sec)

Aww, det är illa va? Naturligtvis specificerade vi inte where-satsen:

mysql> select id, material, color from carpet where color='Light Yellow'
    -> union
    -> select id, material, color from curtain where color='Light Yellow';
+------+-----------+--------------+
| id   | material  | color        |
+------+-----------+--------------+
|    1 | wool      | Light Yellow |
|    3 | polyester | Light Yellow |
|    3 | cotton    | Light Yellow |
+------+-----------+--------------+
3 rows in set (0.00 sec)

En koppling mellan två tabeller på färgen gör att du kan returnera raderna från båda tabellerna i en enda rad med data. Du kan ange sammanfogningen i de två tabellerna för objektets färg och använda en where-sats för att endast returnera de rader du letar efter.

mysql> select a.id, a.material, a.color, b.id, b.material 
    -> from curtain a join carpet b on a.color=b.color;
+------+----------+--------------+------+-----------+
| id   | material | color        | id   | material  |
+------+----------+--------------+------+-----------+
|    3 | cotton   | Light Yellow |    1 | wool      |
|    3 | cotton   | Light Yellow |    3 | polyester |
+------+----------+--------------+------+-----------+
2 rows in set (0.00 sec)

Som du kan se har detta endast returnerat raderna med en matchande färg och tillåtit dig att ha kolumner från båda tabellerna i en enda rad i din resultatuppsättning.

Nu har jag uppenbarligen inte planerat detta särskilt bra eftersom jag inte har några andra matchande resultat förutom "Ljusgult" i båda tabellerna, så om jag lägger till några fler poster i får vi detta:

mysql> select * from curtain;
+------+----------+--------------+
| id   | material | color        |
+------+----------+--------------+
|    1 | Velvet   | Purple       |
|    2 | cotton   | White        |
|    3 | cotton   | Light Yellow |
|    4 | cotton   | Light Blue   |
|    5 | Wool     | White        |
|    6 | Fluff    | Beige        |
+------+----------+--------------+
6 rows in set (0.00 sec)

mysql> select * from carpet;
+------+-----------+--------------+
| id   | material  | color        |
+------+-----------+--------------+
|    1 | wool      | Light Yellow |
|    2 | wool      | Beige        |
|    3 | polyester | Light Yellow |
|    4 | polyester | Light Red    |
|    5 | Fluff     | Light Blue   |
+------+-----------+--------------+
5 rows in set (0.00 sec)

Nu kan vi köra det igen, och den här gången får vi:

mysql> select a.id, a.material, a.color, b.id, b.material 
    -> from curtain a join carpet b on a.color=b.color;
+------+----------+--------------+------+-----------+
| id   | material | color        | id   | material  |
+------+----------+--------------+------+-----------+
|    3 | cotton   | Light Yellow |    1 | wool      |
|    3 | cotton   | Light Yellow |    3 | polyester |
|    4 | cotton   | Light Blue   |    5 | Fluff     |
|    6 | Fluff    | Beige        |    2 | wool      |
+------+----------+--------------+------+-----------+
4 rows in set (0.00 sec)

Åh nej!

Det är nu vi använder join- och where-satsen tillsammans:

mysql> select a.id, a.material, a.color, b.id, b.material 
    -> from curtain a join carpet b on a.color=b.color 
    -> where a.color='Light Yellow';
+------+----------+--------------+------+-----------+
| id   | material | color        | id   | material  |
+------+----------+--------------+------+-----------+
|    3 | cotton   | Light Yellow |    1 | wool      |
|    3 | cotton   | Light Yellow |    3 | polyester |
+------+----------+--------------+------+-----------+
2 rows in set (0.00 sec)

Du förstår, i SQL finns det ofta fler sätt att få samma resultat på olika sätt än det finns varianter av samma data i dina tabeller.

Edit:Okej, så om du bara vill ha rader där alla data matchar, inkludera bara den i join-syntaxen:

mysql> select a.id, a.material, a.color, b.id, b.material 
    -> from curtain a 
    -> join carpet b on a.color=b.color
    -> and a.id=b.id
    -> where a.color='Light Yellow';
+------+----------+--------------+------+-----------+
| id   | material | color        | id   | material  |
+------+----------+--------------+------+-----------+
|    3 | cotton   | Light Yellow |    3 | polyester |
+------+----------+--------------+------+-----------+
1 row in set (0.00 sec)

Som du kan se säger vi nu till joinen att både id och color fält måste matcha mellan de två tabellerna - och resultaten talar för sig själva. Nu, i det här fallet, är jag tekniskt sett fortfarande matchade inte ALLA kolumner då materialet är annorlunda. Om du ville matcha ytterligare skulle frågan inte returnera några resultat eftersom jag inte har några matchande poster där id, material OCH färg matchar, men syntaxen skulle vara som följer:

mysql> select a.id, a.material, a.color, b.id, b.material 
    -> from curtain a 
    -> join carpet b on a.color=b.color
    -> and a.id=b.id
    -> and a.material=b.material
    -> where a.color='Light Yellow';
Empty set (0.00 sec)

På det sättet vill du i de flesta fall inte ha alla kolumnerna för att matcha. Mycket ofta har tabeller ett ID som bara används för den tabellen och är ett automatiskt ökande värde. Du vill använda den för att identifiera en unik rad i den tabell, men inte att använda den för att matcha orelaterade tabeller. Om något så skulle jag ha föreslagit att du matchar material och färg - men lämna ID-numret utanför det.



  1. fackets prestation kontra fackets alla

  2. 3 sätt att returnera rader som innehåller alfanumeriska tecken i SQL Server

  3. EF 6 - Hur man korrekt utför parallella frågor

  4. Hur får man ut antalet totala resultat när det finns LIMIT i fråga?