2011-09-15 27 views
39

Aquí está mi pregunta simple SQL ...¿Cómo contar el número de instancias de cada ID de clave externa en una tabla?

Tengo dos tablas:

Libros

------------------------------------------------------- 
| book_id | author | genre | price | publication_date | 
------------------------------------------------------- 

órdenes

------------------------------------ 
| order_id | customer_id | book_id | 
------------------------------------ 

que me gustaría crear una consulta que devuelve:

-------------------------------------------------------------------------- 
| book_id | author | genre | price | publication_date | number_of_orders | 
-------------------------------------------------------------------------- 

En otras palabras, devuelva cada columna para TODAS las filas en la tabla Libros, junto con una columna calculada llamada 'number_of_orders' que cuenta el número de veces que cada libro aparece en la tabla Pedidos. . (Si un libro no se da en la tabla de pedidos, el libro debería ser listados en el conjunto de resultados, pero "number_of_orders" debe ser cero

Hasta el momento, se me ha ocurrido con esto:

SELECT 
    books.book_id, 
    books.author, 
    books.genre, 
    books.price, 
    books.publication_date, 
    count(*) as number_of_orders 
from books 
left join orders 
on (books.book_id = orders.book_id) 
group by 
    books.book_id, 
    books.author, 
    books.genre, 
    books.price, 
    books.publication_date 

Eso es casi derecho, pero no del todo, porque "number_of_orders" serán 1, incluso si un libro no aparece en la tabla Pedidos. por otra parte, dada mi falta de conocimientos de SQL, estoy seguro de que esto la consulta es muy ineficiente.

¿Cuál es la forma correcta de escribir esta consulta? (Por lo que vale, esto tiene que funcionar en MySQL, por lo que no puedo usar ninguna otra característica específica del proveedor).

¡Gracias de antemano!

Respuesta

62

Su consulta es casi correcta y es la forma correcta de hacerlo (y el más eficiente)

SELECT books.*, count(orders.book_id) as number_of_orders   
from books 
left join orders 
on (books.book_id = orders.book_id) 
group by 
    books.book_id 

COUNT(*) podría incluir valores nulos en el recuento, ya que cuenta con todo las filas, mientras que COUNT(orders.book_id) no lo hace porque ignora los valores NULOS en el campo dado.

+2

Su última afirmación podría ser algo engañoso. La función COUNT ignora los valores NULL cuando agrega datos. El motivo por el que COUNT (*) devuelve los recuentos incorrectos aquí es porque cuenta las filas en lugar de una columna específica. Solo quiero aclarar para el OP –

+0

Actualicé la respuesta, thx. – Fabio

+0

@Fabio ¿Cómo se llama esta consulta en particular, para contar entradas relacionadas en otra tabla? ¿Tiene algún nombre académico? –

5

Cambio count(*) a count(orders.book_id)

1

Está contando algo equivocado. Desea contar los book_id no nulos.

SELECT 
    books.book_id, 
    books.author, 
    books.genre, 
    books.price, 
    books.publication_date, 
    count(orders.book_id) as number_of_orders 
from books 
left join orders 
on (books.book_id = orders.book_id) 
group by 
    books.book_id, 
    books.author, 
    books.genre, 
    books.price, 
    books.publication_date 
4
SELECT b.book_id, 
    b.author, 
    b.genre, 
    b.price, 
    b.publication_date, 
    coalesce(oc.Count, 0) as number_of_orders 
from books b 
left join (
    select book_id, count(*) as Count 
    from Order 
    group by book_id 
) oc on (b.book_id = oc.book_id) 
Cuestiones relacionadas