PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Tworzenie zapytania, które zwraca id, jeśli warunek jest dopasowany w wierszach z dwóch tabel

Przeczytałem Twoje pytanie w Meta o tym konkretnym pytaniu, pozwól mi wyjaśnić, dlaczego wszystkie trzy odpowiedzi są rzeczywiście poprawne - podobnie jak sposób, w jaki to rozwiązałeś.

Podałem przykłady wszystkich trzech odpowiedzi i schematu, nad którym pracują:

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)

(kilka instrukcji wstawiania)

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)

Przecięcie używa dwóch instrukcji select i zwraca pasujące wyniki. W tym przypadku szukasz wszystkich wierszy, które mają pasujący kolor „Jasnożółty”.

Nie mogę podać przykładu w MySQL, ponieważ go nie obsługuje (jak widać poniżej, nie jest to konieczne, aby uzyskać te same wyniki).

Zapytanie składające składające się z dwóch instrukcji select, z których każda zawiera klauzulę WHERE zezwalającą tylko na kolor „Jasnożółty”, zwróci te same dane. Chociaż unii można użyć do zwrócenia danych, które nie są zgodne, klauzula where w każdej instrukcji SELECT oznacza, że ​​zwróci ona tylko żądane wiersze.

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)

Oj, to źle, prawda? Oczywiście nie określiliśmy klauzuli 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)

Połączenie między dwiema tabelami w kolorze pozwoli zwrócić wiersze z obu tabel w jednym wierszu danych. Możesz określić łączenie w dwóch tabelach dla koloru elementu i użyć klauzuli where, aby zwrócić tylko te wiersze, których szukasz.

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)

Jak widać, zwróciło to tylko wiersze z pasującym kolorem i pozwoliło na umieszczenie kolumn z obu tabel w jednym wierszu zestawu wyników.

Teraz najwyraźniej nie zaplanowałem tego zbyt dobrze, ponieważ nie mam innych pasujących wyników poza „jasnożółtym” w obu tabelach, więc jeśli dodam kilka dodatkowych wpisów, otrzymamy to:

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)

Teraz możemy uruchomić to ponownie i tym razem uzyskać:

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)

O nie!

W tym miejscu używamy razem klauzuli join i klauzuli 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)

Widzisz, w SQL jest często więcej sposobów na uzyskanie tego samego wyniku różnymi sposobami niż w przypadku wariacji tych samych danych w twoich tabelach.

Edycja:OK, więc jeśli chcesz tylko wiersze, w których wszystkie dane są zgodne, po prostu uwzględnij je w składni sprzężenia:

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)

Jak widać, teraz informujemy złączenia, że ​​oba id i color pola muszą się zgadzać między dwiema tabelami - a wyniki mówią same za siebie. W tym przypadku technicznie nadal nie pasuje do WSZYSTKICH kolumn, ponieważ materiał jest inny. Jeśli chciałbyś dopasować dalej, zapytanie nie zwróci żadnych wyników, ponieważ nie mam pasujących rekordów, w których identyfikator, materiał i kolor są zgodne, ale składnia byłaby następująca:

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)

Pamiętaj jednak, że w większości przypadków nie chcesz wszystkich kolumny do dopasowania. Bardzo często tabele mają identyfikator, który jest używany tylko dla tej tabeli i jest automatycznie zwiększającą się wartością. Chcesz go użyć do zidentyfikowania unikalnego wiersza w tym tabeli, ale nie używaj jej do dopasowywania niepowiązanych tabel. Jeśli już, to sugerowałbym dopasowanie materiału i koloru - ale pomiń identyfikator.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zamień znaki na ciągi wieloznakowe

  2. Konwerter typu identyfikatora agregatu Axon

  3. Sprawianie, by plik database.yml działał w Railsach na OSX

  4. Pobieranie wierszy za pomocą zapytania sprzężenia

  5. Błąd podczas importowania CSV do postgresa za pomocą pythona i psycopg2