2012-03-06 4 views
0

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

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

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

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 

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

ответ

1

Это потому, что 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 | 
+-----------+-------------+-------------+ 

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

+0

Примечание. Это же соглашение для столбца total_contacts. –

+0

Будь! Большое спасибо за этот подробный ответ, хотелось бы, чтобы я мог дать вам 10-кратные пальцы! Еще раз спасибо. – MacMac

Смежные вопросы