La réponse de Randy est proche, mais la déclaration où supprime toute mention de ces éléments ne font pas partie de toutes les commandes dans cette plage de dates. Notez que «jointure à gauche» est différent des tables de liaison dans la clause where de la manière que vous avez effectuée (c'est-à-dire, jointures internes). Je vous suggère de lire sur les différents types de jointures SQL (interne, externe, croix).
En substance, vous devez joindre les données que vous obtenez de la requête de Randy par rapport à votre liste d'éléments source. L'utilisation d'une sous-sélection permet de faire ceci:
SELECT
name
, nvl(count, 0) as count
FROM
menu_items items
LEFT JOIN (
SELECT
menu_items.id
, SUM(order_items.quantity) as count
FROM
menu_items
LEFT JOIN order_items ON menu_items.id = order_items.menu_item_id
LEFT JOIN orders ON orders.id = order_items.order_id
WHERE
"date" between to_date('2008-11-01','YYYY-MM-DD') and to_date('2008-11-30','YYYY-MM-DD')
GROUP BY
menu_items.id
) counts on items.id = counts.id;
Ceci est dans Oracle 10g BTW. Je doute que vous utilisiez Oracle, vous devrez donc le convertir dans votre propre base de données.
Exécution d'un test montre les éléments suivants:
SQL> create table menu_items (id number, name varchar2(10));
create table order_items (order_id number, menu_item_id number, quantity number);
create table orders (id number, "date" date);
Table created.
SQL>
Table created.
SQL>
Table created.
SQL>
insert into menu_items values (1, 'bread');
insert into menu_items values (2, 'milk');
insert into menu_items values (3, 'honey');
insert into menu_items values (4, 'cheese');
SQL>
1 row created.
SQL>
1 row created.
SQL>
1 row created.
SQL>
1 row created.
SQL>
insert into orders values (1, to_date('2008-11-02', 'YYYY-MM-DD'));
insert into orders values (2, to_date('2008-11-03', 'YYYY-MM-DD'));
insert into orders values (3, to_date('2008-10-29', 'YYYY-MM-DD'));SQL>
1 row created.
SQL>
1 row created.
SQL>
insert into order_items values (1, 1, 1);
insert into order_items values (1, 3, 1);
1 row created.
SQL>
1 row created.
SQL>
insert into order_items values (2, 1, 1);
insert into order_items values (2, 2, 1);
insert into order_items values (2, 3, 1);
insert into order_items values (3, 4, 10);
1 row created.
SQL>
1 row created.
SQL>
1 row created.
SQL>
1 row created.
SQL> SQL>
1 row created.
SQL>
SELECT
name
, nvl(count, 0) as count
FROM
menu_items items
LEFT JOIN (
SELECT
menu_items.id
, SUM(order_items.quantity) as count
FROM
menu_items
LEFT JOIN order_items ON menu_items.id = order_items.menu_item_id
LEFT JOIN orders ON orders.id = order_items.order_id
WHERE
"date" between to_date('2008-11-01','YYYY-MM-DD') and to_date('2008-11-30','YYYY-MM-DD')
GROUP BY
menu_iteSQL> 2 3 4 5 6 7 ms.id
) counts on items.id = counts.id; 8 9 10 11 12 13 14 15 16 17 18
NAME COUNT
---------- ----------
bread 2
milk 1
honey 2
cheese 0
SQL>
drop table menu_items;
drop table order_items;
drop table orders;SQL>
Table dropped.
SQL>
Table dropped.
SQL>
Table dropped.
SQL>
PS: Il est une mauvaise pratique d'utiliser « date » comme nom de colonne comme il est (dans la plupart des cas) un nom de type et peut causer des problèmes aux requêtes et analyse
Bonne affaire, Jamie. 1 sous-requête en moins que la mienne, et beaucoup plus raisonnable. La seule chose qui aura besoin de changer pour MySQL sera de supprimer les fonctions de la fonction de date d'Oracle. +1 – Randy
Mes exigences étaient évidemment un peu plus complexes que la requête que j'ai posté, mais j'ai utilisé cela pour continuer et ça fonctionne parfaitement maintenant. Merci beaucoup. –