#mysql #sql
Вопрос:
Я использую MYSQL, и у меня есть таблица сообщений, как показано ниже.
ID | parent_id | sender_id | receiver_id | Содержание | прочитано | sender_deleted | receiver_deleted | создано |
---|---|---|---|---|---|---|---|---|
18 | 0 | 6 | 1 | testab | 0 | 0 | 0 | 2021-10-28 01:13:42 |
19 | 18 | 6 | 1 | testcd | 0 | 0 | 0 | 2021-10-28 01:14:55 |
Я пытаюсь объединить два запроса в один. Выбор и подсчет, где прочитанное значение равно 0.
Этот запрос выбирает запрос.
SELECT * FROM message
WHERE (sender_id = 1 OR receiver_id = 1) AND (id = 18 OR parent_id = 18);
И этот запрос является запросом подсчета.
SELECT COUNT(id) FROM message
WHERE (sender_id = 1 OR receiver_id = 1)
AND (id = 18 OR parent_id = 18) AND (readed = 0);
Я пытаюсь объединить эти два, используя ЛЕВОЕ СОЕДИНЕНИЕ.
SELECT a.id, a.parent_id, a.content, COUNT(b.id) AS unreaded_message
FROM message a
LEFT JOIN message c ON a.id = c.id AND (readed = 0)
GROUP BY A.ID, A.Date
ORDER BY a.id;
Но я получаю ошибку, как показано ниже.
ERROR 1054 (42S22): Unknown column 'b.id' in 'field list'
Есть ли способ, которым я могу оставить запрос на подсчет количества соединений?
Ответ №1:
Я замечаю эти проблемы при тестировании запроса:
- Неправильный псевдоним
b.id
дляCOUNT()
. Вот где ошибка. - Несуществующая таблица
A.Date
frommessage
. Основываясь на вашем примере таблицы, у вас нет столбца с именем asDate
. Вместо этого у вас есть столбец с именемcreated
, в котором хранится дата время. - Сам запрос несовместим с
sql_mode=only_full_group_by
.only_full_group_by
Начиная с MySQL версии 5.7.5, этот параметр включен по умолчанию по очень веской причине: «если режим выключен, сервер может выбирать любое значение из каждой группы, поэтому, если они не совпадают, выбранные значения являются недетерминированными, что, вероятно, не то, что выхотите (см.: «Обработка MySQL Group By» документы.
Теперь, если я не ошибаюсь, content
сохраняет текстовые сообщения, правильно? И поскольку id=19
parent is id=18
, он должен быть в той же строке, а общее количество непрочитанных сообщений равно 2
. Я не уверен, что это то, что вы действительно ищете, но я опубликую два запроса; один — для решения вашей текущей проблемы, а другой — чтобы предположить, что это, возможно, то, что вы ищете.
Для вашей текущей проблемы вы можете достичь желаемого результата без самостоятельного объединения, и вместо использования COUNT()
вы можете использовать SUM()
CASE
выражение with, как показано ниже:
SELECT id, parent_id, content,
SUM(CASE WHEN readed=0 THEN 1 ELSE 0 END) AS unreaded_message
FROM message
GROUP BY id, parent_id, content;
COUNT()
будет принимать каждую строку в результате запроса в зависимости от ваших условий. Замена SUM()
с CASE
выражением здесь просто сообщает запросу:
SUM(CASE WHEN readed=0 THEN 1 ELSE 0 END) AS unreaded_message
-- if the readed column is 0 (zero) then give it 1, else give it 0 then add them up.
Второе предложение, которое у меня есть, это предположим, что у вас есть больше строк в таблице, подобной этой:
ID | parent_id | sender_id | receiver_id | Содержание | прочитано | sender_deleted | receiver_deleted | создано |
---|---|---|---|---|---|---|---|---|
18 | 0 | 6 | 1 | testab | 1 | 0 | 0 | 2021-10-28 01:13:42 |
19 | 18 | 6 | 1 | testcd | 1 | 0 | 0 | 2021-10-28 01:14:55 |
20 | 18 | 6 | 1 | testde | 0 | 0 | 0 | 2021-10-28 01:15:05 |
21 | 0 | 6 | 1 | testfg | 0 | 0 | 0 | 2021-10-28 02:34:11 |
22 | 21 | 6 | 1 | тесты | 0 | 0 | 0 | 2021-10-28 02:44:01 |
При id
наличии 18,19
обоих readed=1
запросов запрос, который у вас есть, и тот, который я предложил выше, вернет результат, подобный этому:
ID | parent_id | Содержание | unreaded_message |
---|---|---|---|
18 | 0 | testab | 0 |
19 | 18 | testcd | 0 |
20 | 18 | testde | 1 |
21 | 0 | testfg | 1 |
22 | 21 | тесты | 1 |
Но у меня такое чувство, что вы, вероятно, хотите что-то вроде этого:
m_id | Содержание | unreaded_message |
---|---|---|
18 | testde | 1 |
21 | testgf testhi |
2 |
Если это возможно, вы можете просто запустить этот запрос:
SELECT CASE WHEN parent_id=0 THEN id ELSE parent_id END AS m_id,
GROUP_CONCAT(CASE WHEN readed=0
THEN content ELSE '' END
ORDER BY readed, id SEPARATOR 'rn' ) AS contents,
SUM(CASE WHEN readed=0 THEN 1 ELSE 0 END) AS unreaded_message
FROM message
GROUP BY m_id;
Комментарии:
1. Большое вам спасибо. Это то, чего я действительно хотел.
Ответ №2:
Вы используете в запросе псевдоним B в параметре «ПОДСЧЕТ». Вам нужно использовать псевдоним A или C, как в этом примере:
SELECT a.id, a.parent_id, a.content, COUNT(c.id) AS unreaded_message
FROM message a
LEFT JOIN message c ON a.id = c.id AND (readed = 0)
GROUP BY A.ID, A.Date
ORDER BY a.id;