Использование SUM для подсчета трех таблиц с соответствующими записями - PullRequest
0 голосов
/ 06 марта 2012

Я пытаюсь использовать функцию SUM для подсчета строк из 3 таблиц, что, однако, неэффективно, поскольку, когда возвращаются total_files и total_notes, они оба одинаковы, когда есть в хотя бы один файл, а затем total_files примет то же значение, что и total_notes, что я не понимаю, зачем он это делает.

Следует подсчитать количество строк, относящихся к каждой записи, которая будет возвращена в виде списка записей с количеством файлов, общим количеством заметок и общим числом контактов, назначенных записи на строку записи (данные файлов, заметки). и контакты не отображаются, только считаются).

Мой запрос показан ниже:

SELECT rec.street_number,
       rec.street_name,
       rec.city,
       rec.state,
       rec.country,
       rec.latitude,
       rec.longitude,
       LEFT(rec.description, 250) AS description,
       usr.username,
       usr.full_name,
       ppl.person_id,
       ppl.first_name,
       ppl.last_name,
       SUM(IF(rlk.record_id = rec.record_id, 1, 0)) AS total_contacts,
       SUM(IF(files.record_id = rec.record_id, 1, 0)) AS total_files,
       SUM(IF(notes.record_id = rec.record_id, 1, 0)) AS total_notes,
       (
           SELECT COUNT(DISTINCT rec.record_id)
           FROM records rec
           WHERE rec.marked_delete = 0 AND rec.is_archive = 0
       ) AS total_records
FROM
(
    records rec

    INNER JOIN members usr ON rec.user_id = usr.user_id

    LEFT OUTER JOIN record_links rlk ON rec.record_id = rlk.record_id

    LEFT OUTER JOIN people ppl ON ppl.person_id = rlk.person_id AND rlk.record_id = rec.record_id

    LEFT OUTER JOIN files files ON files.record_id = rec.record_id

    LEFT OUTER JOIN notes notes ON notes.record_id = rec.record_id
)
WHERE rec.marked_delete = 0 AND rec.is_archive = 0
GROUP BY rec.record_id
ORDER BY rec.submit_date DESC
LIMIT 0, 25

В принципе, как вы можете видеть, есть three SUM, который будет подсчитывать соответствующие строки из этих таблиц, но я серьезно не понимаю, как total_files будет принимать то же значение, что и total_notes что-то не так я здесь делаю?

1 Ответ

1 голос
/ 06 марта 2012

Это потому, что rec соединен с и notes и files.

Предположим, что запись 1 содержит 2 заметки и 1 файл, запись 2 содержит две заметки и два файлаи в записи 3 есть примечание, но нет файлов.

Тогда таблица rec LEFT OUTER JOIN files ... LEFT OUTER JOIN notes будет выглядеть следующим образом:

+-----------+---------+---------+
| record_id | file_id | note_id |
+-----------+---------+---------+
|         1 |       1 |       1 |
|         1 |       2 |       1 |
|         2 |       3 |       2 |
|         2 |       3 |       3 |
|         2 |       4 |       2 |
|         2 |       4 |       3 |
|         3 |    NULL |       4 |
+-----------+---------+---------+

Обратите внимание, как каждый file_id объединяется с каждым note_id(в том же record_id).Кроме того, поскольку у вас есть SUM(IF(files.record_id = rec.record_id,1,0)) и условие соединения files.record_id = rec.record_id, вы фактически считаете COUNT(files)*COUNT(notes) за record_id.

Я бы порекомендовал вам вместо COUNT(DISTINCT files.id)и COUNT(DISTINCT records.id).Столбец в COUNT будет вашим основным ключом для files / notes, , а не files.record_id:

SELECT rec.record_id,
       COUNT(DISTINCT files.id) AS total_files,
       COUNT(DISTINCT notes.id) AS total_notes
FROM rec
-- note: LEFT OUTER JOIN is the same as LEFT JOIN in MySQL
LEFT JOIN files ON files.record_id=rec.record_id 
LEFT JOIN notes ON notes.record_id=rec.record_id
GROUP BY record_id


+-----------+-------------+-------------+
| record_id | total_files | total_notes |
+-----------+-------------+-------------+
|         1 |           2 |           1 |
|         2 |           2 |           2 |
|         3 |           0 |           1 |
+-----------+-------------+-------------+

Конечно, при необходимости настройте свой запрос.(добавить в эти дополнительные столбцы / объединения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...