PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Criando consulta que retorna id se a condição for correspondida em linhas de duas tabelas


Li sua pergunta no Meta sobre essa questão em particular, deixe-me explicar por que todas as três respostas estão realmente corretas - como é a maneira como você resolveu.

Incluí exemplos de todas as três respostas e o esquema em que estão trabalhando:
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)

(grupo de instruções de inserção)
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)

Uma interseção usa duas instruções select e traz de volta resultados correspondentes. Nesse caso, você está procurando todas as linhas que tenham uma cor correspondente de 'Amarelo claro'.

Não posso dar um exemplo no MySQL, pois ele não o suporta (como você pode ver abaixo, não é necessário fornecer os mesmos resultados).

Uma consulta de união de duas instruções select, cada uma com uma cláusula where, permitindo apenas a cor 'Amarelo claro', retornará os mesmos dados. Embora uma união possa ser usada para retornar dados que não correspondem, a cláusula where em cada instrução select significa que ela retornará somente as linhas desejadas.
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, isso é ruim certo? Obviamente, não especificamos a cláusula 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)

Uma junção entre duas tabelas na cor permitirá que você retorne as linhas de ambas as tabelas em uma única linha de dados. Você pode especificar a junção nas duas tabelas para a cor do item e usar uma cláusula where para retornar apenas as linhas que você está procurando.
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)

Como você pode ver, isso retornou apenas as linhas com uma cor correspondente e permitiu que você tivesse colunas de ambas as tabelas em uma única linha do seu conjunto de resultados.

Agora, eu claramente não planejei isso muito bem, pois não tenho outros resultados correspondentes além do 'Amarelo claro' em ambas as tabelas, então, se eu adicionar mais algumas entradas, obteremos isso:
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)

Agora podemos executar isso novamente, e desta vez obter:
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)

Ah não!

Agora é onde usamos a cláusula join e where juntas:
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)

Veja bem, no SQL geralmente há mais maneiras de obter o mesmo resultado por meios diferentes do que variações dos mesmos dados em suas tabelas.

Editar:Ok, então se você quiser apenas linhas onde todos os dados correspondem, basta incluí-lo na sintaxe de junção:
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)

Como você pode ver, agora informamos à junção que tanto o id e color campos devem corresponder entre as duas tabelas - e os resultados falam por si. Agora, neste caso, eu tecnicamente ainda não correspondeu a TODAS as colunas, pois o material é diferente. Se você quisesse corresponder ainda mais, a consulta não retornaria nenhum resultado, pois não tenho registros correspondentes em que o id, o material E a cor correspondam, mas a sintaxe seria a seguinte:
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)

No entanto, na maioria dos casos, você não quer todos as colunas para corresponder. Muitas vezes, as tabelas têm um ID que é usado apenas para essa tabela e é um valor de incremento automático. Você deseja usá-lo para identificar uma linha exclusiva que tabela, mas não para usá-la para corresponder a tabelas não relacionadas. Se qualquer coisa, eu teria sugerido que você combinasse em material e cor - mas deixe o ID de fora.