SQL JOIN - cláusula WHERE vs. cláusula ON


686

Después de leerlo, este no es un duplicado de uniones explícitas vs implícitas de SQL . La respuesta puede estar relacionada (o incluso la misma) pero la pregunta es diferente.


¿Cuál es la diferencia y qué debe ir en cada uno?

Si entiendo la teoría correctamente, el optimizador de consultas debería poder usar ambos indistintamente.


2
Solo para futuros lectores y su información, debe leer el orden de ejecución de SQL. Esto lo ayudaría más precisamente a comprender la diferencia subyacente.
Rahul Neekhra

Respuestas:


869

No són la misma cosa.

Considere estas consultas:

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID
WHERE Orders.ID = 12345

y

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID 
    AND Orders.ID = 12345

El primero devolverá un pedido y sus líneas, si corresponde, para el número de pedido 12345. El segundo devolverá todos los pedidos, pero solo el pedido 12345tendrá líneas asociadas.

Con un INNER JOIN, las cláusulas son efectivamente equivalentes. Sin embargo, el hecho de que sean funcionalmente iguales, ya que producen los mismos resultados, no significa que los dos tipos de cláusulas tengan el mismo significado semántico.


83
¿obtendrá un mejor rendimiento al poner la cláusula where en la cláusula "on" para una unión interna?
FistOfFury

96
@FistOfFury Sql Server utiliza un procedimiento optimizador de consultas que compila y evalúa su código para producir el mejor plan de ejecución posible. No es perfecto, pero la mayoría de las veces no importará y obtendrá el mismo plan de ejecución de cualquier manera.
Joel Coehoorn

18
En Postgres noté que NO eran equivalentes y dieron como resultado diferentes planes de consulta. Si usa ON, resultó en el uso de materializar. Si usaste WHERE, usó un hash. El materializar tenía un caso peor que era 10 veces más costoso que el hash. Esto estaba usando un conjunto de ID en lugar de una sola ID.
JamesHutchison

13
@JamesHutchison Es difícil hacer generalizaciones de rendimiento confiables basadas en comportamientos observados como este. Lo que era cierto un día tiende a ser incorrecto al siguiente, porque este es un detalle de implementación en lugar de un comportamiento documentado. Los equipos de bases de datos siempre están buscando lugares para mejorar el rendimiento del optimizador. Me sorprendería si el comportamiento ON no mejora para coincidir con el WHERE. Puede que ni siquiera aparezca en ninguna parte de las notas de la versión de una versión a otra que no sea algo así como "mejoras generales de rendimiento."
Joel Coehoorn

44
@FiHoran Así no es como funciona Sql Server. Prefiltrará agresivamente según los elementos de la cláusula WHERE cuando las estadísticas muestren que puede ser útil.
Joel Coehoorn

362
  • No importa para las uniones internas
  • Asuntos para juntas externas

    a. WHEREcláusula: Después de unirse. Los registros se filtrarán después de que se haya realizado la unión.

    si. ONcláusula - Antes de unirse. Los registros (de la tabla derecha) se filtrarán antes de unirse. Esto puede terminar como nulo en el resultado (desde la unión OUTER).



Ejemplo : considere las siguientes tablas:

    1. documents:
     | id    | name        |
     --------|-------------|
     | 1     | Document1   |
     | 2     | Document2   |
     | 3     | Document3   |
     | 4     | Document4   |
     | 5     | Document5   |


    2. downloads:
     | id   | document_id   | username |
     |------|---------------|----------|
     | 1    | 1             | sandeep  |
     | 2    | 1             | simi     |
     | 3    | 2             | sandeep  |
     | 4    | 2             | reya     |
     | 5    | 3             | simi     |

a) WHERECláusula interna :

  SELECT documents.name, downloads.id
    FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
    WHERE username = 'sandeep'

 For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 1                  | Document1    | 2                   | 1           | simi     |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 2                  | Document2    | 4                   | 2           | reya     |
    | 3                  | Document3    | 5                   | 3           | simi     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

  After applying the `WHERE` clause and selecting the listed attributes, the result will be: 

   | name         | id |
   |--------------|----|
   | Document1    | 1  |
   | Document2    | 3  | 

b) JOINcláusula interior

  SELECT documents.name, downloads.id
  FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
        AND username = 'sandeep'

For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 3                  | Document3    | NULL                | NULL        | NULL     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

Notice how the rows in `documents` that did not match both the conditions are populated with `NULL` values.

After Selecting the listed attributes, the result will be: 

   | name       | id   |
   |------------|------|
   |  Document1 | 1    |
   |  Document2 | 3    | 
   |  Document3 | NULL |
   |  Document4 | NULL | 
   |  Document5 | NULL | 

40
OMI, esta es la mejor respuesta porque demuestra claramente lo que está sucediendo 'bajo el capó' de las otras respuestas populares.
psrpsrpsr

1
Excelente explicación ... ¡bien hecho! - Por curiosidad, ¿qué hiciste para conseguir eso intermediate join table? ¿Algún comando 'Explicar'?
Manuel Jordan

1
@ManuelJordan No, esto es solo para explicación. Una base de datos puede hacer algo más eficaz que crear una tabla intermedia.
Sandeep Jindal

Entendido, supuse que tal vez se usó una tercera herramienta.
Manuel Jordan

145

En INNER JOINs son intercambiables, y el optimizador los reorganizará a voluntad.

En OUTER JOINs, no son necesariamente intercambiables, dependiendo de qué lado de la unión dependen.

Los pongo en cualquier lugar dependiendo de la legibilidad.



Probablemente sea mucho más claro en la cláusula Where, especialmente en expresiones lambda de Linq-To-EntitiesOrders.Join( OrderLines, x => x.ID, x => OrderID, (o,l) => new {Orders = o, Lines = l}).Where( ol => ol.Orders.ID = 12345)
Triynko

49

La forma en que lo hago es:

  • Siempre ponga las condiciones de unión en la ONcláusula si está haciendo un INNER JOIN. Por lo tanto, no agregue ninguna condición WHERE a la cláusula ON, colóquelas en la WHEREcláusula.

  • Si está haciendo un LEFT JOIN, agregue cualquier condición WHERE a la ONcláusula para la tabla en el lado derecho de la unión. Esto es imprescindible, porque agregar una cláusula WHERE que haga referencia al lado derecho de la unión la convertirá en una UNIÓN INTERNA.

    La excepción es cuando busca los registros que no están en una tabla en particular. Se podría añadir la referencia a un identificador único (que no es siempre NULL) en el RIGHT JOIN tabla a la cláusula WHERE de esta manera: WHERE t2.idfield IS NULL. Por lo tanto, la única vez que debe hacer referencia a una tabla en el lado derecho de la unión es encontrar aquellos registros que no están en la tabla.


8
Esta es la mejor respuesta que he leído sobre esto hasta ahora. Totalmente tiene sentido una vez que su cerebro entiende una combinación izquierda se va a devolver todas las filas en la tabla de la izquierda y hay que filtrarla después.
Nick Larsen

si se une externamente a una tabla con una columna anulable, ¿aún puede "dónde" esa columna es nula sin convertirla en una unión interna? Eso no es exactamente buscar los registros que no están en una tabla en particular solamente. Puede buscar 1. no existe 2. no tiene ningún valor.
Cerca del

Quiero decir que puedes buscar ambos: "1. no existió 2. no tiene ningún valor" juntos. Y esto se aplica al caso en que ese campo no es idfield.
Cerca del

Cuando me encontré con este caso: buscando participantes incluyendo estudiantes de primer año (datos aún no ingresados) sin un contacto de emergencia.
Cerca del

30

En una unión interna, significan lo mismo. Sin embargo, obtendrá resultados diferentes en una unión externa dependiendo de si coloca la condición de unión en la cláusula WHERE vs ON. Eche un vistazo a esta pregunta relacionada y esta respuesta (por mí).

Creo que tiene más sentido tener el hábito de poner siempre la condición de unión en la cláusula ON (a menos que sea una unión externa y realmente lo desee en la cláusula where), ya que lo hace más claro para cualquiera que lea su consulta en qué condiciones se unen las tablas, y también ayuda a evitar que la cláusula WHERE tenga docenas de líneas de largo.


26

Esta es una pregunta muy común, por lo que esta respuesta se basa en este artículo que escribí.

Relación de mesa

Teniendo en cuenta que tenemos lo siguiente posty las post_commenttablas:

Las tablas <code> post </code> y <code> post_comment </code>

El posttiene los siguientes registros:

| id | title     |
|----|-----------|
| 1  | Java      |
| 2  | Hibernate |
| 3  | JPA       |

y post_commenttiene las siguientes tres filas:

| id | review    | post_id |
|----|-----------|---------|
| 1  | Good      | 1       |
| 2  | Excellent | 1       |
| 3  | Awesome   | 2       |

SQL INNER JOIN

La cláusula SQL JOIN le permite asociar filas que pertenecen a diferentes tablas. Por ejemplo, CROSS JOIN creará un producto cartesiano que contiene todas las combinaciones posibles de filas entre las dos tablas de unión.

Si bien CROSS JOIN es útil en ciertos escenarios, la mayoría de las veces, desea unir tablas en función de una condición específica. Y ahí es donde entra en juego INNER JOIN.

SQL INNER JOIN nos permite filtrar el producto cartesiano de unir dos tablas en función de una condición que se especifica mediante la cláusula ON.

SQL INNER JOIN - CONdición "siempre verdadera"

Si proporciona una condición "siempre verdadera", INNER JOIN no filtrará los registros unidos, y el conjunto de resultados contendrá el Producto cartesiano de las dos tablas de unión.

Por ejemplo, si ejecutamos la siguiente consulta SQL INNER JOIN:

SELECT
   p.id AS "p.id",
   pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1

Obtendremos todas las combinaciones posty post_commentregistros:

| p.id    | pc.id      |
|---------|------------|
| 1       | 1          |
| 1       | 2          |
| 1       | 3          |
| 2       | 1          |
| 2       | 2          |
| 2       | 3          |
| 3       | 1          |
| 3       | 2          |
| 3       | 3          |

Por lo tanto, si la condición de la cláusula ON es "siempre verdadera", INNER JOIN es simplemente equivalente a una consulta CROSS JOIN:

SELECT
   p.id AS "p.id",
   pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id

SQL INNER JOIN - CONdición "siempre falsa"

Por otro lado, si la condición de la cláusula ON es "siempre falsa", todos los registros unidos se filtrarán y el conjunto de resultados estará vacío.

Entonces, si ejecutamos la siguiente consulta SQL INNER JOIN:

SELECT
   p.id AS "p.id",
   pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id

No obtendremos ningún resultado:

| p.id    | pc.id      |
|---------|------------|

Esto se debe a que la consulta anterior es equivalente a la siguiente consulta CROSS JOIN:

SELECT
   p.id AS "p.id",
   pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id

SQL INNER JOIN - cláusula ON utilizando las columnas Clave externa y Clave primaria

La condición de cláusula ON más común es la que coincide con la columna Clave externa en la tabla secundaria con la columna Clave primaria en la tabla primaria, como se ilustra en la siguiente consulta:

SELECT
   p.id AS "p.id",
   pc.post_id AS "pc.post_id",
   pc.id AS "pc.id",
   p.title AS "p.title",
   pc.review  AS "pc.review"
FROM post p
INNER JOIN post_comment pc ON pc.post_id = p.id
ORDER BY p.id, pc.id

Al ejecutar la consulta SQL INNER JOIN anterior, obtenemos el siguiente conjunto de resultados:

| p.id    | pc.post_id | pc.id      | p.title    | pc.review |
|---------|------------|------------|------------|-----------|
| 1       | 1          | 1          | Java       | Good      |
| 1       | 1          | 2          | Java       | Excellent |
| 2       | 2          | 3          | Hibernate  | Awesome   |

Por lo tanto, solo los registros que coinciden con la condición de la cláusula ON se incluyen en el conjunto de resultados de la consulta. En nuestro caso, el conjunto de resultados contiene todo postjunto con sus post_commentregistros. Las postfilas que no tienen asociadas post_commentse excluyen ya que no pueden cumplir la condición de la cláusula ON.

Nuevamente, la consulta SQL INNER JOIN anterior es equivalente a la siguiente consulta CROSS JOIN:

SELECT
   p.id AS "p.id",
   pc.post_id AS "pc.post_id",
   pc.id AS "pc.id",
   p.title AS "p.title",
   pc.review  AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id

Las filas no tachadas son las que satisfacen la cláusula WHERE, y solo estos registros se incluirán en el conjunto de resultados. Esa es la mejor manera de visualizar cómo funciona la cláusula INNER JOIN.

El | p.id | pc.post_id | pc.id | p.title | pc.review |
| ------ | ------------ | ------- | ----------- | --------- - |
El | 1 | 1 | 1 | Java | Bueno |
El | 1 | 1 | 2 | Java | Excelente |
El | 1 | 2 | 3 | Java | Impresionante | 
El | 2 | 1 | 1 | Hibernar | Bueno | 
El | 2 | 1 | 2 | Hibernar | Excelente |
El | 2 | 2 | 3 | Hibernar | Impresionante |
El | 3 | 1 | 1 | JPA | Bueno | 
El | 3 | 1 | 2 | JPA | Excelente | 
El | 3 | 2 | 3 | JPA | Impresionante |

Conclusión

Una declaración INNER JOIN puede reescribirse como CROSS JOIN con una cláusula WHERE que coincida con la misma condición que usó en la cláusula ON de la consulta INNER JOIN.

No es que esto solo se aplique a INNER JOIN, no a OUTER JOIN.


11

Existe una gran diferencia entre la cláusula where frente de la cláusula , cuando se trata de unirse a izquierda.

Aquí hay un ejemplo:

mysql> desc t1; 
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| fid   | int(11)     | NO   |     | NULL    |       |
| v     | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

Allí fid es id de la tabla t2.

mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| v     | varchar(10) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

Consulta sobre "en cláusula":

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id AND t1.v = 'K' 
    -> ;
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  1 |   1 | H | NULL | NULL |
|  2 |   1 | B | NULL | NULL |
|  3 |   2 | H | NULL | NULL |
|  4 |   7 | K | NULL | NULL |
|  5 |   5 | L | NULL | NULL |
+----+-----+---+------+------+
5 rows in set (0.00 sec)

Consulta sobre "cláusula where":

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id where t1.v = 'K';
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  4 |   7 | K | NULL | NULL |
+----+-----+---+------+------+
1 row in set (0.00 sec)

Está claro que, la primera consulta devuelve un registro de t1 y su fila dependiente de t2, si la hay, para la fila t1.v = 'K'.

La segunda consulta devuelve filas de t1, pero solo para t1.v = 'K' tendrá una fila asociada.


9

En términos del optimizador, no debería hacer una diferencia si define sus cláusulas de unión con ON o WHERE.

Sin embargo, en mi humilde opinión, creo que es mucho más claro usar la cláusula ON al realizar uniones. De esa manera, tiene una sección específica de su consulta que dicta cómo se maneja la combinación en lugar de entremezclarse con el resto de las cláusulas WHERE.


7

Consideremos esas tablas:

UNA

id | SomeData

si

id | id_A | SomeOtherData

id_A ser una clave foránea para la mesa A

Escribiendo esta consulta:

SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A;

Proporcionará este resultado:

/ : part of the result
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////+-------+-------------------------+
|/////////////////////////////|
+-----------------------------+

Lo que está en A pero no en B significa que hay valores nulos para B.


Ahora, consideremos una parte específica B.id_Ay destaquémosla del resultado anterior:

/ : part of the result
* : part of the result with the specific B.id_A
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////+---+///|                         |
|/////////////////////|***|///|                         |
|/////////////////////+---+---+-------------------------+
|/////////////////////////////|
+-----------------------------+

Escribiendo esta consulta:

SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A
AND B.id_A = SpecificPart;

Proporcionará este resultado:

/ : part of the result
* : part of the result with the specific B.id_A
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|/////////////////////|       |                         |
|/////////////////////|       |                         |
|/////////////////////+---+   |                         |
|/////////////////////|***|   |                         |
|/////////////////////+---+---+-------------------------+
|/////////////////////////////|
+-----------------------------+

Porque esto elimina en la unión interna los valores que no están en B.id_A = SpecificPart


Ahora, cambiemos la consulta a esto:

SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A
WHERE B.id_A = SpecificPart;

El resultado es ahora:

/ : part of the result
* : part of the result with the specific B.id_A
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|                     |       |                         |
|                     |       |                         |
|                     +---+   |                         |
|                     |***|   |                         |
|                     +---+---+-------------------------+
|                             |
+-----------------------------+

Debido a que todo el resultado se filtra contra la B.id_A = SpecificParteliminación de las partes B.id_A = NULL, que están en A que no están en B


4

¿Estás intentando unir datos o filtrar datos?

Para facilitar la lectura, tiene más sentido aislar estos casos de uso en ON y WHERE respectivamente.

  • unir datos en ON
  • filtrar datos en DONDE

Puede resultar muy difícil leer una consulta donde la condición JOIN y una condición de filtrado existen en la cláusula WHERE.

En cuanto al rendimiento, no debería ver una diferencia, aunque diferentes tipos de SQL a veces manejan la planificación de consultas de manera diferente, por lo que vale la pena intentarlo ¯\_(ツ)_/¯ (tenga en cuenta que el almacenamiento en caché afecta la velocidad de la consulta)

Además, como otros han señalado, si usa una unión externa obtendrá resultados diferentes si coloca la condición del filtro en la cláusula ON porque solo afecta a una de las tablas.

Escribí una publicación más detallada sobre esto aquí: https://dataschool.com/learn/difference-between-where-and-on-in-sql


2

En SQL, la cláusula 'WHERE' y 'ON' son una especie de Statemants condicionales, pero la principal diferencia entre ellos es la cláusula 'Where' que se utiliza en las declaraciones de selección / actualización para especificar las condiciones, mientras que la cláusula 'ON' se usa en Uniones, donde verifica o verifica si los Registros coinciden en las tablas de destino y fuente, antes de unir las Tablas

Por ejemplo: - 'DÓNDE'

SELECT * FROM employee WHERE employee_id=101

Por ejemplo: - 'ENCENDIDO'

Hay dos tablas employee y employee_details, las columnas coincidentes son employee_id.

SELECT * FROM employee 
INNER JOIN employee_details 
ON employee.employee_id = employee_details.employee_id

Espero haber respondido tu pregunta. Revertir para cualquier aclaración.


Pero podría usar la palabra clave WHEREen lugar de ON, ¿no? sqlfiddle.com/#!2/ae5b0/14/0
Qwerty

1

Creo que es el efecto de secuencia de unión. En el caso de unión superior izquierda, SQL debe unirse primero a la izquierda y luego hacer dónde filtrar. En el caso de la decepción, primero encuentre Orders.ID = 12345 y luego únase.


1

Para una unión interna, WHEREy ONse puede usar indistintamente. De hecho, es posible usar ONen una subconsulta correlacionada. Por ejemplo:

update mytable
set myscore=100
where exists (
select 1 from table1
inner join table2
on (table2.key = mytable.key)
inner join table3
on (table3.key = table2.key and table3.key = table1.key)
...
)

Esto (IMHO) es completamente confuso para un ser humano, y es muy fácil olvidarse de vincular table1a cualquier cosa (porque la tabla "driver" no tiene una cláusula "on"), pero es legal.


1

Para obtener un mejor rendimiento, las tablas deben tener una columna indexada especial para usar en JOINS.

así que si la columna que condiciona no es una de esas columnas indexadas, entonces sospecho que es mejor mantenerla en DONDE.

entonces se UNE usando las columnas indexadas, luego, después de UNIRSE, ejecuta la condición en la columna no indexada.


1

Normalmente, el filtrado se procesa en la cláusula WHERE una vez que las dos tablas ya se han unido. Sin embargo, es posible que desee filtrar una o ambas tablas antes de unirlas. es decir, la cláusula where se aplica a todo el conjunto de resultados, mientras que la cláusula on solo se aplica a la combinación en cuestión.


Esto no es así ya que los DBMS se optimizan "normalmente".
philipxy

1

Creo que esta distinción puede explicarse mejor a través del orden lógico de operaciones en SQL , que es simplificado:

  • FROM (incluidas las uniones)
  • WHERE
  • GROUP BY
  • Agregaciones
  • HAVING
  • WINDOW
  • SELECT
  • DISTINCT
  • UNION` INTERSECT`EXCEPT
  • ORDER BY
  • OFFSET
  • FETCH

Las uniones no son una cláusula de la instrucción select, sino un operador dentro de FROM. Como tal, todas las ONcláusulas que pertenecen al JOINoperador correspondiente "ya han sucedido" lógicamente para cuando el procesamiento lógico llega a la WHEREcláusula. Esto significa que, en el caso de una LEFT JOIN, por ejemplo, la semántica de la unión externa ya ha sucedido cuando WHEREse aplica la cláusula.

He explicado el siguiente ejemplo más en profundidad en esta publicación de blog . Al ejecutar esta consulta:

SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
WHERE film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;

El LEFT JOINrealmente no tiene ningún efecto útil, porque incluso si un actor no jugó en una película, el actor se filtrará, como FILM_IDserá, NULLy la WHEREcláusula filtrará dicha fila. El resultado es algo como:

ACTOR_ID  FIRST_NAME  LAST_NAME  COUNT
--------------------------------------
194       MERYL       ALLEN      1
198       MARY        KEITEL     1
30        SANDRA      PECK       1
85        MINNIE      ZELLWEGER  1
123       JULIANNE    DENCH      1

Es decir, como si interiormente uniéramos las dos tablas. Si movemos el predicado de filtro en la ONcláusula, ahora se convierte en un criterio para la unión externa:

SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
  AND film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;

Lo que significa que el resultado contendrá actores sin películas, o sin películas con FILM_ID < 10

ACTOR_ID  FIRST_NAME  LAST_NAME     COUNT
-----------------------------------------
3         ED          CHASE         0
4         JENNIFER    DAVIS         0
5         JOHNNY      LOLLOBRIGIDA  0
6         BETTE       NICHOLSON     0
...
1         PENELOPE    GUINESS       1
200       THORA       TEMPLE        1
2         NICK        WAHLBERG      1
198       MARY        KEITEL        1

En breve

Siempre coloque su predicado donde tenga más sentido, lógicamente.


0

Con respecto a su pregunta,

Es lo mismo 'on' o 'where' en una unión interna siempre que su servidor pueda obtenerlo:

select * from a inner join b on a.c = b.c

y

select * from a inner join b where a.c = b.c

La opción 'dónde' no todos los intérpretes lo saben, por lo que tal vez debería evitarse. Y, por supuesto, la cláusula 'on' es más clara.


-5

Esta es mi solución.

SELECT song_ID,songs.fullname, singers.fullname
FROM music JOIN songs ON songs.ID = music.song_ID  
JOIN singers ON singers.ID = music.singer_ID
GROUP BY songs.fullname

Debes tener elGROUP BY de conseguir que funcione.

Espero que esto ayude.


10
Agrupar solo canciones.fullname mientras también selecciona song_id y cantantes.fullname será un problema en la mayoría de las bases de datos.
btilly
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.