Ответ Рэнди близок, но оператор where удаляет любое упоминание тех предметов, которые не входят ни в какие заказы в этом диапазоне дат.
Обратите внимание, что "левое соединение" отличается от связывания таблиц в предложении where тем же способом, что и вы (т.е. внутренние соединения). Я предлагаю вам ознакомиться с различными типами соединений 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_items.id
) counts on items.id = counts.id;
Это в Oracle 10g BTW. Я сомневаюсь, что вы используете Oracle, поэтому вам нужно конвертировать в вашу собственную базу данных.
Выполнение теста показывает следующее:
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: плохой практикой является использование «даты» в качестве имени столбца, так как оно (в большинстве случаев) является именем типа и может вызвать проблемы при запросах и синтаксическом анализе.