MySql запрос справки: соединения с суммами и счетами - PullRequest
1 голос
/ 27 марта 2009

У меня есть такая структура базы данных:

TBL_A  |  TBL_B  |  TBL_C  |  TBL_D  | TBL_E
-------+---------+---------+---------+----------
id     | id_tbla | id_tbla | id_tbla | id
name   | id_user | id_user | id_user | name_tbla
...    | is_bool |         | weight  | id_user

Вот что я пытаюсь достичь:

SELECT 
    a.id, 
    a.name, 
    b.is_bool,
    count(c.id_user) AS nb_views, 
    sum(d.weight) AS total_weight,
    count(distinct e.id_user) AS distinct_users,
FROM TBL_A AS a 
LEFT JOIN (TBL_B AS b) on (b.id_tbla = a.id)
LEFT JOIN (TBL_C AS c) on (c.id_tbla = a.id)
LEFT JOIN (TBL_D AS d) on (d.id_tbla = a.id)
LEFT JOIN (TBL_E AS e) on (e.name_tbla = a.name)
where a.id = 1 and e.id_user = 1

Запрос выполняется, но результаты (nb_views, total_weight, different_users) неверны. Есть идеи почему?

1 Ответ

1 голос
/ 27 марта 2009

Вы пытаетесь вычислить слишком много агрегатов в одном запросе.

Enita non sunt multiplicanda praeter Необходимость

(лат. «Сущности не умножаются сверх необходимости»)

Ваши таблицы B, C, D и E производятся Декартовы произведения друг против друга. Предположим, данная строка в A соответствует:

  • 3 строки в B
  • 6 строк в C
  • 4 строки в D
  • 1 строка в E

Общее количество строк в результате составляет 3 * 6 * 4 * 1 = 72 строки. Таким образом, ваше count(c.id_user) в 12 раз больше, чем должно быть, ваше sum(d.weight) в 18 раз больше, чем должно быть и т. Д.

Самое простое средство - вычислить каждый из этих агрегатов в отдельном запросе:

SELECT a.id, a.name, COALESCE(b.is_bool, FALSE) AS is_bool
FROM TBL_A AS a LEFT JOIN TBL_B AS b ON (b.id_tbla = a.id)
WHERE a.id = 1;

SELECT a.id, COUNT(c.id_user) AS nb_views
FROM TBL_A AS a LEFT JOIN TBL_C AS c ON (c.id_tbla = a.id)
WHERE a.id = 1;

SELECT a.id, SUM(d.weight) AS total_weight,
FROM TBL_A AS a LEFT JOIN TBL_D AS d ON (d.id_tbla = a.id)
WHERE a.id = 1;

SELECT a.id, COUNT(DISTINCT e.id_user) AS distinct_users,
FROM TBL_A AS a LEFT JOIN TBL_E AS e 
  ON (e.name_tbla = a.name AND e.id_user = 1)
WHERE a.id = 1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...