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