2011-02-05 12 views
5

Próbuję określić wynik wpisu, znajdując różnicę między liczbą upvotes i downvotes, które otrzymał w MYSQL, uruchamiając SELECT (SELECT COUNT(vote_id) AS vote_up FROM głosów WHERE vote='UP'),(SELECT COUNT(vote_id) AS vote_down FROM głosów WHERE vote='DOWN'),(vote_up - vote_down AS vote_score). Kiedy próbuję to uruchomić, mówi mi, że nie mam odpowiedniej składni. Co ja robię źle?Uzyskiwanie różnicy między licznikami dwóch podkwerendy

Czy istnieje lepszy sposób na napisanie tego?

Na koniec, jaki jest idealny sposób na znalezienie przedmiotu o najwyższej i najniższej liczbie głosów? Czy po prostu ORDER BY [above query]?

Odpowiedz

3

Można to zrobić z

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 

Zauważ, że lepszym rozwiązaniem jest mieć +1 lub -1 przechowywane w głosowaniu, to można po prostu zrobić:

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

BTW jeśli formatowanie wygląda na dziwnego, wyjaśniłem to w http://bentilly.blogspot.com/2011/02/sql-formatting-style.html.

+1

+1 jednak pojawi się błąd z powodu braku klauzuli "GROUP BY". –

+0

Wow, dzięki! To działało idealnie. Twój post był dobrą lekturą, chociaż zwykle nie mam do czynienia z bardzo długimi pytaniami ... – nickles

+0

@ Scrum Meister: Masz rację. Naprawiony. Moim największym życzeniem dla SQL jest to, że gdybym nie miał GROUP BY, to odkryłbym, co powinno być oparte na moim SELECT ... – btilly

1

Nawiązując do odpowiedzi btilly, o ile trzeba wiedzieć, najniższa i najwyższa ale zrobić nie muszą wiedzieć, jakie ID ma najwyższy/najniższy:

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

Jeśli trzeba znać identyfikator , użyj zapytania wewnętrznego (dodaj ID do wyboru) za pomocą ORDER BY score LIMIT 1, aby uzyskać najniższą wartość, a ORDER BY score DESC LIMIT 1, aby uzyskać najwyższą wartość. uwaga w przypadku więzi, to wybierze tylko 1 z nich.

+0

Dzięki za to! Niestety, potrzebuję id wpisu i wartości pomiędzy. – nickles

4

Można to zrobić poprzez pociągnięcie tej ostatniej klauzuli w (SELECT ...) bloku, a także:

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; 

Uwaga btilly na odpowiedź o konieczności +/- 1 będzie reprezentacja upvote/downvote. To sprawia, że ​​o wiele więcej sensu w tym kontekście, a także pozwala na szybsze mniejszych tabel, porównań, a korzystanie z funkcji SUM() gdy konieczne:

SELECT SUM(vote) from votes; 

Należy również pamiętać: Dostaniesz tylko vote_up i vote_down liczy stosując wielokrotność (SELECT ...) method - SUM(CASE) poda tylko sumę.

+1

Cóż, czuję się głupio, że odstąpiłem od początkowego SELECT dla trzeciego zapytania. – nickles

+2

Jedyną odpowiedzią, która NAPRAWDĘ odpowiada na pytanie w tytule –

Powiązane problemy