PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Creazione di una query che restituisce id se la condizione è soddisfatta nelle righe di due tabelle

Ho letto la tua domanda su Meta su questa particolare domanda, lascia che ti spieghi perché tutte e tre le risposte sono effettivamente corrette, così come il modo in cui l'hai risolto.

Ho incluso esempi di tutte e tre le risposte e lo schema su cui stanno lavorando:

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)

(gruppo di dichiarazioni di inserimento)

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)

Un'intersezione utilizza due istruzioni select e riporta i risultati corrispondenti. In questo caso, stai cercando tutte le righe che hanno un colore corrispondente di "Giallo chiaro".

Non posso darti un esempio in MySQL perché non lo supporta (come puoi vedere di seguito, non è necessario per dare gli stessi risultati).

Una query di unione di due istruzioni select ciascuna con una clausola where che consente solo il colore di "Giallo chiaro" restituirà gli stessi dati. Sebbene un'unione possa essere utilizzata per restituire dati che non corrispondono, la clausola where in ogni istruzione select significa che restituirà solo le righe desiderate.

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, è brutto vero? Ovviamente non abbiamo specificato la clausola where:

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)

Un join tra due tabelle sul colore ti consentirà di restituire le righe di entrambe le tabelle in un'unica riga di dati. Puoi specificare il join sulle due tabelle per il colore dell'elemento e utilizzare una clausola where per restituire solo le righe che stai cercando.

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)

Come puoi vedere, questo ha restituito solo le righe con un colore corrispondente e ti ha permesso di avere colonne di entrambe le tabelle in una singola riga del tuo set di risultati.

Ora, chiaramente non l'ho pianificato molto bene poiché non ho altri risultati corrispondenti a parte il "Giallo chiaro" in entrambe le tabelle, quindi se aggiungo alcune voci in più otteniamo questo:

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)

Ora possiamo eseguirlo di nuovo e questa volta ottenere:

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)

Oh no!

Ora è qui che usiamo insieme la clausola join e where:

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)

Vedi, in SQL ci sono spesso più modi per ottenere lo stesso risultato con mezzi diversi rispetto alle variazioni degli stessi dati nelle tue tabelle.

Modifica:OK, quindi se vuoi solo righe in cui tutti i dati corrispondono, basta includerli nella sintassi di join:

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)

Come puoi vedere, ora diciamo al join che sia il id e color i campi devono corrispondere tra le due tabelle e i risultati parlano da soli. Ora, in questo caso, tecnicamente ancora non corrispondeva a TUTTE le colonne poiché il materiale è diverso. Se si desidera eseguire ulteriori corrispondenze, la query non restituirà alcun risultato poiché non ho record corrispondenti in cui l'ID, il materiale E il colore corrispondono, ma la sintassi sarebbe la seguente:

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)

Tuttavia, nella maggior parte dei casi, non vuoi tutti le colonne da abbinare. Molto spesso le tabelle hanno un ID che viene utilizzato solo per quella tabella ed è un valore che si incrementa automaticamente. Vuoi usarlo per identificare una riga univoca in quella tabella, ma non per usarlo per abbinare tabelle non correlate. Se non altro, ti avrei suggerito di abbinare materiale e colore, ma lascia fuori l'ID.