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 означает "Мне нравится", 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
но все, что я получаю, это два раза, что неудивительно.
Единственное решение, которое я могу придумать, это иметь отдельный столбец "нравится и не нравится"
3 ответа
Вы можете сделать это с помощью агрегированного запроса, используя противоположные условия в одном столбце 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
Обновление: согласно обсуждению в комментариях ниже, столбец like/dislike может быть нормализован в свою собственную таблицу, например так (пример намеренно глупый...):
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. Предположим, что вы вводите запись в эту таблицу, когда пользователь впервые просматривает бюллетень, по умолчанию делая его "Не определенным", и обновляете эту запись, когда голосуют в бюллетене. Вы можете запросить результаты так:
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
таблица и связанные запросы.
Для записи, есть другой способ получить тот же набор результатов, будь то быстрее или медленнее, зависит от платформы. Это использует скалярный подзапрос вместо агрегата во внешнем запросе. Идея в том, что это должно быть проще, если вы думаете с точки зрения множеств. Или с точки зрения измерения фактов.
Сначала мы должны выяснить ваши имена. Давайте назовем ваш "стол"
bulletin_like
и основной бюллетень таблицыbulletin
(bulletin_id
это очень глупое имя для любого из них, это скорее название столбца). И просто вызвать логическую колонкуlike
(если это 1,like
правда; если это 0,like
ложно; вот что значит логическое значение). Используйте единственную форму для имен.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
Вы попросили тег нормализации. Тот
bulletin_like
"таблица" не нормируется. Избавиться отId
В этом столбце он не служит никакой другой цели, кроме избыточного столбца и дополнительного индекса. ПК является(bulletin_id, user_id)
,Если вы не хотите, чтобы пользователи публиковали несколько лайков и дислайков за постер в бюллетене.
Этот запрос работал для меня:
SELECT bulletin_id,
sum(like_dislike) AS likes,
sum((1-like_dislike)) AS dislikes
FROM bulletins_ld
GROUP BY (bulletin_id);
Предполагается, что likesislike = 1 означает "НРАВИТСЯ ЕГО", а likesislike = 0 означает "НЕ НРАВИТСЯ ЕГО".
ID LIKES DISLIKES
1 2 1
2 0 1