2011-02-05 9 views
5

Estoy tratando de determinar el puntaje de una entrada al encontrar la diferencia entre el número de upvotes y downvotes que ha recibido en MYSQL al ejecutar SELECT (SELECT COUNT(vote_id) AS vote_up FROM votos WHERE vote='UP'),(SELECT COUNT(vote_id) AS vote_down FROM votos WHERE vote='DOWN'),(vote_up - vote_down AS vote_score). Sin embargo, cuando intento ejecutar esto, me dice que no tengo la sintaxis adecuada. ¿Qué estoy haciendo mal?Obteniendo la diferencia entre los recuentos de dos subconsultas

Además, ¿hay una mejor manera de escribir esto?

Y, por último, ¿cuál es la forma ideal de encontrar el artículo con el mayor y menor número de votos? ¿Podría solo ORDER BY [above query]?

Respuesta

3

Puede hacerlo con

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 

Tenga en cuenta que el mejor enfoque es tener 1 o -1 almacenado en la votación, a continuación, puedes hacer:

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

Por cierto si mi formato te parece extraño, lo expliqué en http://bentilly.blogspot.com/2011/02/sql-formatting-style.html.

+1

+1 Sin embargo, recibirá un error por omitir una cláusula 'GROUP BY'. –

+0

¡Guau, gracias! Esto funcionó perfectamente. Y tu publicación fue una buena lectura, aunque normalmente no trato con consultas que son muy largas ... – nickles

+0

@The Scrum Meister: Tienes razón. Fijo. Mi mayor deseo para SQL es que, si no tuviera un GROUP BY, supiera lo que debería basarse en mi SELECT ... – btilly

1

El seguimiento de la respuesta de btilly, si usted necesita saber el más bajo y más alto, pero hace no necesidad de saber lo que tiene identificador de la más alta/baja:

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

Si necesita saber el ID , utilice la consulta interna (agregue el ID a la selección) con un ORDER BY score LIMIT 1 para obtener el más bajo y ORDER BY score DESC LIMIT 1 para obtener el más alto. nota en el caso de los vínculos, esto elegirá solo 1 de ellos.

+0

¡Gracias por esto! Desafortunadamente, necesito la identificación de la entrada y los valores intermedios. – nickles

4

Puede hacerlo tirando en esa última cláusula en un bloque (SELECT ...) así: Respuesta

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; 

Nota del btilly de tener +/- 1 ser la representación upvote/downvote. Tiene mucho más sentido en este contexto, y permite comparaciones tablas más pequeñas, más rápidas, y el uso de la función SUM() cuando sea necesario:

SELECT SUM(vote) from votes; 

También tenga en cuenta: Sólo se obtendrá vote_up y vote_down cuenta usando el múltiple (SELECT ...) método - SUM(CASE) solo le dará el total.

+1

Bueno, me siento tonto por dejar el SELECT inicial para la tercera consulta ahora. – nickles

+2

La única respuesta que REALMENTE responde la pregunta en el título –

Cuestiones relacionadas