Внутреннее объединение с количеством () на трех таблицах

Простой и быстрый вопрос, у меня есть те таблицы:

//table people
| pe_id | pe_name |
| 1  | Foo  |
| 2  | Bar  |
//orders table
| ord_id | pe_id | ord_title   |
|   1    |   1   | First order |
|   2    |   2   | Order two   |
|   3    |   2   | Third order |
//items table
| item_id | ord_id | pe_id | title  |
|   1     |   1    |   1   | Apple  |
|   2     |   1    |   1   | Pear   |
|   3     |   2    |   2   | Apple  |
|   4     |   3    |   2   | Orange |
|   5     |   3    |   2   | Coke   |
|   6     |   3    |   2   | Cake   |

У меня должен быть запрос, перечисляющий всех людей, считая количество заказов и общее количество объектов, как этот:

| pe_name | num_orders | num_items |
| Foo  |    1       |   2       |
| Bar  |    2       |   4       |

Но я не могу заставить его работать! Я попробовал

SELECT
    people.pe_name,
    COUNT(orders.ord_id) AS num_orders,
    COUNT(items.item_id) AS num_items
FROM
    people
    INNER JOIN orders ON (orders.pe_id = people.pe_id)
    INNER JOIN items ON items.pe_id = people.pe_id
GROUP BY
    people.pe_id;

Но это возвращается num_* неправильные значения:

| name | num_orders | num_items |
| Foo  |    2       |   2       |
| Bar  |    8       |   8       |

Я заметил, что, если я пытаюсь присоединиться к одной таблице во время, она работает:

SELECT
    people.pe_name,
    COUNT(orders.ord_id) AS num_orders
FROM
    people
    INNER JOIN orders ON (orders.pe_id = people.pe_id)
GROUP BY
    people.pe_id;

//give me:
| pe_name | num_orders |
| Foo     |          1 |
| Bar     |          2 |

//and:
SELECT
    people.pe_name,
    COUNT(items.item_id) AS num_items
FROM
    people
    INNER JOIN items ON (items.pe_id = people.pe_id)
GROUP BY
    people.pe_id;
//output:
| pe_name | num_items |
| Foo     |         2 |
| Bar     |         4 |

Как объединить те два запроса в одном?

22
задан Péter Török 29 June 2010 в 14:13
поделиться

3 ответа

Более логично объединять элемент с заказами, чем с людьми!

SELECT
    people.pe_name,
    COUNT(distinct orders.ord_id) AS num_orders,
    COUNT(items.item_id) AS num_items
FROM
    people
    INNER JOIN orders ON orders.pe_id = people.pe_id
         INNER JOIN items ON items.ord_id = orders.ord_id
GROUP BY
    people.pe_id;

Соединение предметов с людьми вызывает много дублонов. Например, элементы торта в порядке 3 будут связаны с заказом 2 через соединение между людьми, и вы не хотите, чтобы это произошло !!

Итак:

1- Вам нужно хорошо понимать свою схему. Предметы связаны с заказами, а не с людьми.

2- Вам нужно подсчитывать отдельные заказы для одного человека, иначе вы будете считать столько же предметов, сколько заказов.

34
ответ дан 29 November 2019 в 04:29
поделиться

Как указал Фрэнк, вам нужно использовать DISTINCT. Кроме того, поскольку вы используете составные первичные ключи (что вполне нормально, кстати), вам необходимо убедиться, что вы используете весь ключ в своих соединениях:

SELECT
    P.pe_name,
    COUNT(DISTINCT O.ord_id) AS num_orders,
    COUNT(I.item_id) AS num_items
FROM
    People P
INNER JOIN Orders O ON
    O.pe_id = P.pe_id
INNER JOIN Items I ON
    I.ord_id = O.ord_id AND
    I.pe_id = O.pe_id
GROUP BY
    P.pe_name

Без I.ord_id = O.ord_id он присоединял каждую строку элемента к каждая строка заказа на человека.

5
ответ дан 29 November 2019 в 04:29
поделиться

Ваше решение почти верное. Вы можете добавить DISTINCT:

SELECT
    people.pe_name,
    COUNT(distinct orders.ord_id) AS num_orders,
    COUNT(items.item_id) AS num_items
FROM
    people
    INNER JOIN orders ON (orders.pe_id = people.pe_id)
    INNER JOIN items ON items.pe_id = people.pe_id
GROUP BY
    people.pe_id;
1
ответ дан 29 November 2019 в 04:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: