#mysql #count
#mysql #подсчет
Вопрос:
У меня есть система, в которой, по сути, пользователи могут вводить 3 разные части информации: совет, комментарий и голосование. Эти фрагменты информации сохраняются в 3 разных таблицах. Связующим столбцом каждой таблицы является идентификатор пользователя. Я хочу выполнить запрос, чтобы определить, есть ли у пользователя вообще какие-либо фрагменты информации любого из трех типов. Я пытаюсь сделать это в одном запросе, но получается совершенно неправильно. Вот с чем я сейчас работаю:
SELECT DISTINCT
*
FROM tips T
LEFT JOIN comments C ON T.user_id = C.user_id
LEFT JOIN votes V ON T.user_id = V.user_id
WHERE T.user_id = 1
Похоже, что это только получение подсказок, дублирующихся для стольких голосов или комментариев, даже если голоса или комментарии не были сделаны указанным идентификатором пользователя.
Мне нужно только одно число в ответ, а не отдельные подсчеты каждого типа. В принципе, мне нужна сумма количества советов, комментариев и голосов, сохраненных под этим идентификатором пользователя, но я не хочу выполнять три запроса.
У кого-нибудь есть какие-нибудь идеи?
Редактировать: На самом деле, мне даже технически не нужно фактическое количество, мне просто нужно знать, есть ли какие-либо строки в любой из этих трех таблиц с этим user_id .
Правка 2: у меня почти получилось с этим:
SELECT
COUNT(DISTINCT T.tip_id),
COUNT(DISTINCT C.tip_id),
COUNT(DISTINCT V.tip_id)
FROM tips T
LEFT JOIN comments C ON T.user_id = C.user_id
LEFT JOIN votes V ON T.user_id = V.user_id
WHERE T.user_id = 1
Я тестирую с идентификатором пользователя 1 (me). Я дал 11 советов, проголосовал 4 раза и не сделал никаких комментариев. Мой результат — строка с 3 столбцами: 11, 0, 4. Это правильное количество. Тем не менее, я тестировал это с пользователем, который не давал никаких советов или комментариев, но проголосовал 3 раза, который вернул 0 для всех подсчетов, он должен был вернуть: 0, 0, 3.
Проблема, с которой я сталкиваюсь, похоже, заключается в том, что если в таблице, которую я использую для предложения WHERE, нет строк из этого user_id, то я получаю 0 по всем направлениям, даже если в других таблицах есть строки с этим user_id. Я мог бы использовать этот запрос:
SELECT
(SELECT COUNT(*) FROM tips WHERE user_id = 2)
(SELECT COUNT(*) FROM comments WHERE user_id = 2)
(SELECT COUNT(*) FROM votes WHERE user_id = 2) AS total
Но я действительно хотел избежать выполнения нескольких запросов, даже если это подзапросы, подобные этому.
Обновить
Благодаря ace я разобрался в этом:
SELECT
(COUNT(DISTINCT T.tip_id) COUNT(DISTINCT C.tip_id) COUNT(DISTINCT V.tip_id)) AS total
FROM users U
LEFT JOIN tips T ON U.user_id = T.user_id
LEFT JOIN votes V ON U.user_id = V.user_id
LEFT JOIN comments C ON U.user_id = C.user_id
WHERE U.user_id = 4
таблица users содержит фактическую информацию о пользователе, включая, очевидно, идентификатор пользователя. Я использовал таблицу user в качестве родительской, поскольку я мог быть на 100% уверен, что пользователь будет присутствовать в этой таблице, даже если его не было в других таблицах. Я получил правильное количество, которое хотел, с помощью этого запроса!
Комментарии:
1. Я не уверен, что дизайн вашей базы данных имеет смысл. Возможно, это так, но не похоже на это.
2. Это имеет смысл. Пользователи публикуют подсказку по заданию. Эта подсказка отправляется в таблицу «tips» и содержит, среди прочего, user_id плаката. Другие пользователи могут прокомментировать этот совет, они отправляются в таблицу «комментарии» и также содержат user_id. Наконец, пользователи могут голосовать за подсказки, они сохраняются в таблице «голоса» и также содержат user_id. Это единственный способ сделать это и иметь возможность отслеживать, кто что публикует / делает. Мне нужно определить, проголосовал ли пользователь или опубликовал подсказку или комментарий, чтобы я мог разрешить или запретить им изменять свое отображаемое имя.
3. Причина, по которой вы получаете 0,0,0 вместо 0,0,3, заключается в том, что ваша базовая таблица
tips
не имеет идентификатора пользователя, тогда выLEFT JOIN
вводите в нееvotes
идентификатор пользователя. Сначала все строки будут получены изtips
, а затем, если выLEFT JOIN
сделаете это из другой таблицы. MySQL будет искать каждый идентификатор пользователя, который есть вvotes
, затем присоединится к нему. Тогда все идентификаторы пользователя, которых нет вLEFT table or tips
, будут исключены для получения изvotes
, поэтому вы не получите этот идентификатор пользователя вvotes
. Также у вас возникнет проблема с использованием DISTINCT таким образом, потому что результат каждого равного значения в столбце будет считаться равным 1.
Ответ №1:
Насколько я понимаю ваш вопрос. Вы хотите подсчитать общее количество комментариев советов голосов для каждого пользователя. Хотя мне не совсем понятно, взгляните на запрос ниже. Я добавил столбцы для получения подробной информации, это запрос с перекрестными вкладками, как кто-то научил меня.
ОТРЕДАКТИРОВАННЫЙ ЗАПРОС:
SELECT
COALESCE(COALESCE(t2.tips,0) COALESCE(c2.comments,0) COALESCE(v2.votes,0)) AS `Totals`
FROM parent p
LEFT JOIN (SELECT t.user_id, COUNT(t.tip_id) AS tips FROM tips t GROUP BY t.user_id) t2
ON p.user_id = t2.user_id
LEFT JOIN (SELECT c.user_id, COUNT(c.tip_id) AS comments FROM comments c GROUP BY c.user_id) c2
ON p.user_id = c2.user_id
LEFT JOIN (SELECT v.user_id, COUNT(v.tip_id) AS votes FROM votes v GROUP BY v.user_id) v2
ON p.user_id = v2.user_id
WHERE p.user_id = 1;
Примечание: При этом использовалась родительская таблица для получения результата таблицы, которого нет в другой таблице.
Причина, по которой я использую вложенный запрос в моем объединении, заключается в создании виртуальной таблицы, которая получит сумму tip_id для каждой таблицы. Также у меня возникла проблема с DISTINCT
использованием одного и того же вашего запроса, поэтому в итоге я получаю этот запрос.
Я знаю, что вы предпочитаете не использовать подзапросы, но я потерпел неудачу без подзапроса. На данный момент это все, что я могу.
Комментарии:
1. Мне просто нужно знать, проголосовал ли пользователь или опубликовал совет или комментарий. Если какое-либо из них верно, то количество должно быть больше 0. Проверьте правку в первом сообщении. Во всех трех таблицах есть два одинаковых столбца: user_id и tip_id, поскольку комментарии и голоса связаны с самим tip. В принципе, если какая-либо из трех таблиц содержит строку, где user_id = #, то я должен получить число, большее 0, если ни одна из таблиц не содержит строку, где user_id = #, то количество должно быть равно 0.
2. Я думаю, запрос покажет желаемый результат. Я собираюсь отредактировать имя поля в запросе, чтобы оно соответствовало вашим полям, и добавлю предложение WHERE для ID. Если это все еще не то, что вы ищете, я попытаюсь сделать новый запрос, если у меня будет время.
3. Извините, но я вообще не понимаю ваш запрос. Какова цель выбора в предложении FROM? Вы выбираете строки в предложении, которому требуется таблица. Я получаю всевозможные ошибки, когда пытаюсь его запустить. Мне нужно только одно число взамен. Это число будет суммой количества советов, комментариев и голосов, сделанных указанным идентификатором пользователя. Если пользователь сделал 1 подсказку, без комментариев и 2 голоса, то подсчет будет равен 3. Если они дали 5 советов, 2 комментария и не проголосовали, тогда количество будет равно 7, имеет смысл?
4. Я предполагаю, что причина ошибки в том, что в моем запросе используется другое имя поля, чем в вашем. Когда я прочитал ваш обновленный вопрос, у вас возникла проблема, если идентификатор пользователя не содержится в таблице вашего предложения where. Насколько я понимаю использование объединения в таблицу, результатом 0 будет мой ожидаемый ответ, даже если у вас есть этот user_id в какой-то таблице. Чтобы решить эту проблему, у вас должна быть родительская таблица, которая будет вашей базовой таблицей и будет использоваться в вашем
WHERE
предложении. Вы также не хотите использовать вложенный запрос, поэтому мой запрос соответствует. Сейчас попробуйте добавить родительскую / пользовательскую таблицу.5. Хорошо для вас, я надеюсь, у вас не возникнет проблем с DISTINCT . Если у вас одинаковый user_id и одинаковый tip_id в таблице, это будет засчитываться как 1. Ваш итог будет не таким, как вы ожидали. В любом случае, вы только хотите знать, есть ли у пользователя советы, комментарии и голоса, тогда вы согласны с тем, что у вас есть.