Упорядочить по сумме отсчетов двух полей - PullRequest
3 голосов
/ 22 марта 2011

Хорошо, у меня здесь интересная проблема.У меня есть две таблицы, советы и голоса.Советы выглядят так:

tip_id, challenge_id, user_id, ip_address, tip_date, tip_text

Голоса выглядят так:

tip_id, ip_address, vote_date, vote

Пользователи могут публиковать советы по вызову, тогда как другие пользователи могут голосовать за подсказку большим или большим пальцем вверх или вниз.,Поле голосования в голосах - это bool, 0 - большой палец вниз, 1 - большой палец вверх.Задача может иметь любое количество советов.

Я ломал голову и просто не могу заставить это работать.Мне нужен запрос, который может получить количество голосов "за" и "против" для конкретной подсказки, разницу этих двух чисел (так что если будет 2 голоса "за" и 1 голос "за", разница будет 1) в качестве рейтинга, а такжеданные чаевых из таблицы советов, а затем отсортируйте их с наивысшим рейтингом.Предположим, что у нас есть две подсказки, a и b:

a: 3 вверх, 2 вниз (разность: 1) b: 4 вверх, 1 вниз (разность: 3)

В этом случаеb будет на первом месте, так как он имеет более высокий рейтинг, чем a, большую разницу между количеством голосов «за» и «против».

Так, например, предположим, что у меня есть совет с идентификатором 1, который имеет 4 голосов заи 2 голосов "за", что означает разницу в 2, и этот совет связан с задачей 5, мое возвращение может выглядеть так:

up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"

Теперь это я действительно смог сделать, ноу меня проблемы с получением нескольких строк, если есть несколько советов для вызова.Предположим, что в задании № 5 есть 2 подсказки, и я должен получить такой результат:

up | down | rating | tip_id | tip_date | user_id | tip_text
------------------------------------------------------------
3  | 2    | 1      | 1      | 12345678 | 1       | "this is a tip"
4  | 1    | 3      | 1      | 87654321 | 2       | "this is also a tip"

. При этом каждая подсказка получает свою строку в результате.Сейчас происходит то, что я получаю одну строку со значениями «вверх» и «вниз», представляющими собой общее количество голосов «за» и «против» для этой задачи, а не для чаевых.Таким образом, используя второй пример, приведенный выше, вместо двух отдельных строк я получу одну строку со значением «вверх», имеющим значение 7, и значением «3», равным 3, общее количество голосов «за» и «против» для всех советов по этому вызову.

Я уверен, что это будет связано с объединением и упорядочением по группам, но мне все равно, насколько сложен запрос, я просто не хочу делать это в PHP.В конечном счете, я хочу передать запросу идентификатор запроса и получить от него X строк, где X - количество подсказок для этого идентификатора вызова, и где каждая строка будет содержать значения только для этого идентификатора подсказки.

Любойпомощь будет оценена, так как у меня кончаются волосы, чтобы вытащить.К сожалению, это является определяющей точкой моего проекта, советы с более высоким рейтингом должны появляться выше в списке.

Редактировать: Вот мой текущий, почти рабочий запрос.Я сделал несколько поправок к нему после хорошего ночного сна и заставил его работать в основном, но есть проблема, которую я не могу объяснить:

SELECT
  COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END) AS up,
  COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END) AS down,
  (COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END)) AS rating,
  T.*
  FROM votes V, tips T
  WHERE T.challenge_id = 10
  GROUP BY V.tip_id
  ORDER BY rating DESC

Это дает все, что мне нужно, все советы иголосует за конкретный вызов, с новой строкой для каждого совета (вместо совокупного количества, как я получал раньше).Проблема в том, что мои «за» и «против», а также рейтинг вдвое больше, чем должен быть.Так что, если у меня есть совет, который имеет 3 голоса "за" и 1 голос "против", и поэтому рейтинг 2, этот запрос покажет, что у меня есть 6 голосов "за" и 2 голоса "за" при оценке 4. Я полагаю, я мог бы просто разделитьчисло на два с PHP, но это не решает проблему, это просто бандит.Кто-нибудь может понять, почему я получаю вдвое больше, чем я должен получить?Я буду продолжать возиться с этим, возможно, попробуйте СЛЕДУЮЩЕЕ СОЕДИНЕНИЕ, надеюсь, я это выясню, но было бы неплохо иметь еще несколько пар глаз.

Ответы [ 2 ]

2 голосов
/ 22 марта 2011

Как насчет этого:

SELECT v.up, v.down, (v.up - v.down) AS rating, t.tip_id, t.tip_date, t.user_id, t.tip_text
FROM tips AS t
INNER JOIN votes AS v
ON t.tip_id = v.tip_id
WHERE challenge_id=1
ORDER BY rating DESC;

Затем вы можете установить значение challenge_id предложения WHERE в вашем PHP, прежде чем передавать его в mysql. Я думаю, что это должно дать вам то, что вы ищете, хотя, поскольку я использовал INNER JOIN, вам нужно убедиться, что каждая строка в «подсказках» имеет строку в «голосах», или она будет проигнорирована.

EDIT:

На основании новой информации (извините, я не прочитал вопрос раньше, надеюсь, я понял это правильно!):

 SELECT
  COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END) AS up,
  COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END) AS down,
  (COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END)) AS rating,
  T.*
  FROM votes V
  INNER JOIN tips AS T
  ON T.tip_id = V.tip_id
  WHERE T.challenge_id = 1
  GROUP BY V.tip_id
  ORDER BY rating DESC;

Я только что проверил это в SQLite3 (на упрощенных таблицах), и похоже, что оно работает нормально. Данные, которые я использовал:

sqlite> select * from votes
   ...> ;
tip_id      vote      
----------  ----------
2           1         
2           1         
2           1         
2           0         
2           0         
3           0         
3           0         
3           0         
3           1         
4           0         
4           0         
4           1         
4           1         
4           1         
4           1    

Что дает результат:

up          down        rating      tip_id      challenge_id  user_id   
----------  ----------  ----------  ----------  ------------  ----------
4           2           2           4           1             4         
3           2           1           2           1             2         
1           3           -2          3           1             3         
0 голосов
/ 24 марта 2011

Хорошо, в итоге я изменил запрос, который ianhales предоставил , и получил то, что хотел.С его обновленным wuery я получал правильные счета, но из-за ВНУТРЕННЕГО СОЕДИНЕНИЯ я не получал советы, которые не имели голосов.Мои изменения были просты, но они работают отлично:

SELECT
  COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END) AS up,
  COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END) AS down,
  (COUNT(CASE WHEN V.vote = 1 THEN 'up' ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 'down' ELSE NULL END)) AS rating,
  T.*
  FROM tips T
  LEFT JOIN votes V
  ON T.tip_id = V.tip_id
  WHERE T.challenge_id = 10
  GROUP BY T.tip_id
  ORDER BY rating DESC

Получаются все подсказки, даже если у них нет голосов, и сортируется по рейтинг в порядке убывания, так что вышеСоветы по рейтингу появляются первыми в списке.

Вы были великолепны, и вы можете ожидать, что ваше имя появится в титрах моего проекта.Большое спасибо.

...