Mysql отслеживает пользователей, любит и не любит
Я создаю приложение на доске объявлений. Каждый бюллетень может понравиться или не понравиться пользователям сайта. Чтобы отслеживать симпатии и антипатии, я создал следующую таблицу базы данных.
id user_id bulletin_id like_dislike
1 1 1 1
2 1 2 0
3 3 1 1
4 2 1 0
В столбце like_dislike 1 означает "Like It", 0 означает "Не нравится",
Я знаю, как спросить.
- Сколько раз был бюллетень 1 понравился (2)
- Сколько раз был недопущен бюллетень 1 (1)
Но как я могу сделать запрос, чтобы задать эти два вопроса одновременно? То есть, сколько раз бюллетень 1 любил и не любил
liked disliked
2 1
Я пробовал запрос
SELECT count(like_dislike) AS likes, count(like_dislike) AS dislikes FROM bulletins_ld
where bulletins_id = 1 AND likes = 1 AND dislikes = 0
но все, что я получаю, два раза два, что неудивительно.
Единственное решение, о котором я могу думать, - это отдельный столбец типа "нравится" и "не нравится"
Ответы
Ответ 1
Вы можете сделать это с помощью агрегированного запроса, используя противоположные условия для одного столбца like_dislike (я предполагаю ниже, что "1" в этом столбце означает "понравилось" ).
SELECT bulletin_id,
SUM(CASE WHEN like_dislike = 1 THEN 1 ELSE 0 END) AS likes,
SUM(CASE WHEN like_dislike = 0 THEN 1 ELSE 0 END) AS dislikes
FROM bulletins_ld
GROUP BY bulletin_id
Обновление:. В соответствии с обсуждением в комментариях ниже столбец "как нравится/не нравится" может быть нормализован в свою собственную таблицу, например (пример намеренно глупый...):
CREATE TABLE how_user_feels(
feeling_id INT,
feeling_desc VARCHAR(20)
)
INSERT INTO how_user_feels(feeling_id, feeling_desc) VALUES
(0, 'Undecided'),
(1, 'Likes It'),
(2, 'Could Do Without It')
Столбец Likes_Dislikes в таблице Бюллетеня затем заменяется внешним ключом feeling_id
, по умолчанию равным 0. Скажем, что вы затем вводите запись в эту таблицу, когда пользователь сначала просматривает бюллетень, делая их "Undecided" по умолчанию и обновить эту запись, когда они голосуют в бюллетене. Вы можете запросить результаты следующим образом:
SELECT bulletin_id,
SUM(CASE WHEN feelings_id = 1 THEN 1 ELSE 0 END) AS likes,
SUM(CASE WHEN feelings_id = 2 THEN 1 ELSE 0 END) AS dislikes,
SUM(CASE WHEN feelings_id = 0 THEN 1 ELSE 0 END) AS doesnt_seem_to_care
FROM bulletins_ld b
INNER JOIN how_user_feels h ON b.feeling_id = h.feeling_id
GROUP BY bulletin_id
Имейте в виду, что это всего лишь один подход и, возможно, не будет полезен в вашем случае. Но если вы когда-либо решили изменить или расширить модель, с помощью которой пользователь выражает свои чувства к бюллетеню, скажите пятизвездочной рейтинговой системе, вы можете сделать это без изменения схемы базы данных - просто измените записи в how_user_feels
таблицу и связанные запросы.
Ответ 2
-
Для записи есть другой способ получить тот же набор результатов, будь он быстрее или медленнее, зависит от платформы. Это использует скалярный подзапрос, а не совокупность внешнего запроса. Идея заключается в том, что это должно быть проще, если вы думаете в терминах множеств. Или в терминах измерений-фактов.
Сначала мы должны выпрямить ваши имена. Позвольте называть вашу "таблицу" bulletin_like
, а основная таблица бюллетеней bulletin
(bulletin_id
- очень глупое имя для любого из них, более имени столбца). И просто вызовите булевский столбец like
(если он равен 1, like
- true, если он равен 0, like
- false, то, что означает логическое значение). Используйте уникальную форму для имен.
SELECT name AS bulletin,
(SELECT COUNT(like)
FROM bulletin_like bl
WHERE bl.bulletin_id = b.bulletin_id
AND like = 1
) AS like,
(SELECT COUNT(like)
FROM bulletin_like bl
WHERE bl.bulletin_id = b.bulletin_id
AND like = 0
) AS dislike
FROM bulletin b
-
Вы запросили тег Normalization. Эта таблица bulletin_like
не является нормированной. Избавьтесь от столбца Id
iot, он не имеет никакой цели, кроме избыточного столбца и дополнительного индекса. PK (bulletin_id, user_id)
.
Если вы не хотите, чтобы пользователи размещали множественные симпатии и антипатии к каждому плакату на бюллетень.
Ответ 3
Этот запрос работал у меня:
SELECT bulletin_id,
sum(like_dislike) AS likes,
sum((1-like_dislike)) AS dislikes
FROM bulletins_ld
GROUP BY (bulletin_id);
Это предполагает, что likeisislike = 1 означает "LIKE IT", и likeislike = 0 означает "НЕ НРАВИТСЯ".
ID LIKES DISLIKES
1 2 1
2 0 1