2011-02-05 2 views
5

Я пытаюсь определить оценку записи, установив разницу между количеством повышений и нисходящих потоков, полученных в MYSQL, запустив SELECT (SELECT COUNT(vote_id) AS vote_up FROM голосов WHERE vote='UP'),(SELECT COUNT(vote_id) AS vote_down FROM голосов WHERE vote='DOWN'),(vote_up - vote_down AS vote_score). Когда я пытаюсь запустить это, это говорит мне, что у меня нет правильного синтаксиса. Что я делаю не так?Получение разницы между подсчетами двух подзапросов

Кроме того, есть ли лучший способ написать это?

И, наконец, что является идеальным способом найти предмет с самым высоким и самым низким числом голосов? Я бы просто ORDER BY [above query]?

ответ

3

Вы можете сделать это с

SELECT some_id 
    , SUM(
     CASE 
     WHEN vote = 'UP' 
     THEN 1 
     WHEN vote = 'DOWN' 
     THEN -1 
     ELSE 0 
     END 
    ) as vote_score 
FROM votes 
GROUP BY some_id 

Обратите внимание, что лучший подход должен иметь +1 или -1 хранится в голосовании, то вы можете просто сделать:

SELECT some_id, SUM(vote) as vote_score 
FROM votes 
GROUP BY some_id 

BTW, если мое форматирование выглядит странно, я объяснил это в http://bentilly.blogspot.com/2011/02/sql-formatting-style.html.

+1

+1 однако вы получите ошибку при отсутствии предложения GROUP BY. –

+0

Ничего себе, спасибо! Это сработало отлично. И ваш пост был хорошо прочитан, хотя я обычно не занимаюсь запросами, которые очень долго ... – nickles

+0

@ The Scrum Meister: Вы правы. Исправлена. Мое самое большое желание для SQL заключается в том, что если бы у меня не было GROUP BY, он бы выяснил, на чем он должен основываться на моем SELECT ... – btilly

1

Вслед за ответом btilly, в случае, если вам нужно знать, самый низкий и самый высокий, но делать не нужно знать, что ID имеет самый высокий/низкий:

SELECT MIN(score), MAX(score) 
FROM (
    SELECT SUM(IF(vote = 'DOWN', -1, vote = 'UP')) AS score 
    FROM votes 
    GROUP BY ID 
) 

Если вам не нужно знать ID , используйте внутренний запрос (добавьте ID к выбору) с помощью ORDER BY score LIMIT 1, чтобы получить самое низкое и ORDER BY score DESC LIMIT 1, чтобы получить максимальную оценку. Обратите внимание, что в случае связей это выберет только 1 из них.

+0

Спасибо за это! К сожалению, мне нужен идентификатор записи и значения между ними. – nickles

4

Вы можете сделать это, потянув за эту последнюю фразу в (SELECT ...) блока, а также:

SELECT 
    (SELECT COUNT(vote_id) FROM votes WHERE vote='UP') AS vote_up, 
    (SELECT COUNT(vote_id) FROM votes WHERE vote='DOWN') AS vote_down, 
    (SELECT vote_up - vote_down) AS vote_score 
ORDER BY vote_whatever; 

Примечания btilly Ответит о наличии +/- 1 -представление upvote/downvote. Это делает намного больше смысла в этом контексте, а также позволяет для небольших таблиц, быстрее сравнения, и использование функции SUM() при необходимости:

SELECT SUM(vote) from votes; 

Также обратите внимание: Вы получите только vote_up и vote_down рассчитывает с помощью мультипликатора (SELECT ...) метод - SUM(CASE) даст вам всего.

+1

Ну, я чувствую себя глупо, оставляя исходный SELECT для третьего запроса. – nickles

+2

Единственный ответ, который ДЕЙСТВИТЕЛЬНО отвечает на вопрос в заголовке –

Смежные вопросы