2011-11-28 16 views
8

Tengo dos tablas y trato de encontrar la "publicación" con la puntuación más alta por día.MySQL group by y max devuelve filas incorrectas

CREATE TABLE IF NOT EXISTS `posts_points` (
    `post_id` int(10) unsigned NOT NULL, 
    `comments` smallint(5) unsigned NOT NULL, 
    `likes` smallint(5) unsigned NOT NULL, 
    `favorites` smallint(5) unsigned NOT NULL, 
    PRIMARY KEY (`post_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 


CREATE TABLE IF NOT EXISTS `posts` (
    `profile_id` int(10) unsigned NOT NULL, 
    `post_id` int(10) unsigned NOT NULL, 
    `pubdate_utc` datetime NOT NULL, 
    PRIMARY KEY (`post_id`), 
    KEY `profile_id` (`profile_id`), 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; 

He intentado la consulta a continuación. Devuelve el puntaje correcto pero las otras columnas son solo filas aleatorias. Qué estoy haciendo mal ?

SELECT p.post_id, p.profile_id 
    , MAX(t1.score) 
    , DATE_FORMAT(t1.pubdate_utc, '%d %b') post_date 
    , DATE(t1.pubdate_utc) mydate 
FROM 
(
    SELECT p.profile_id, p.post_id, p.pubdate_utc 
     , (pp.comments + pp.likes + pp.favorites) AS score 
    FROM posts p 
    INNER JOIN posts_points pp ON p.post_id = pp.post_id 
) t1 
INNER JOIN posts p ON t1.post_id = p.post_id 
    AND t1.pubdate_utc = p.pubdate_utc 
GROUP BY mydate 
ORDER BY mydate DESC 
LIMIT 18; 
+2

1 para la inclusión de la definición de tabla – ManseUK

+0

No estás haciendo nada malo.Las funciones agregadas no afectan el valor de otras columnas. Parecerán ser "aleatorias". –

+0

Agrupar por fecha debería generar ese comportamiento extraño. – Alfabravo

Respuesta

0
Column1 Column2 
C  d 
A  any thing 
D  y 
B  z 

Si pide estos datos por Columna1 entonces parece que esto ..... OrdenarPor simplemente ordena a la primera columna ....

Column1 Column2 
A  any thing 
B  z    
C  d 
D  y 
0

es un poco difícil de entender que quieres hacer.

Las palabras (columnas (publicaciones, comentarios, favoritos) y PK), entendí que actualiza los valores cada vez mayores, y no registra cada voto.

este selecto devuelve los datos de la entrada, y la puntuación, ordenando el punto más grande, limitado a 18.

 SELECT P.post_id, 
       P.profile_id, 
       (PP.comments + PP.likes + PP.favorites) AS score, 
       DATE_FORMAT (P.pubdate_utc, '%d %b') AS post_data, 
       DATE (P.pubdate_utc) AS mydate 
      FROM posts P 
    INNER JOIN posts_points PP 
      ON (= P.post_id PP.post_id) 
     ORDER BY 3 DESC 
     LIMIT 18; 

Si que desea seleccionar el mayor número de votos del día, debe grabar los likes/favs diferentes, necesitan datos en esa tabla (posts_points).

+0

'posts_points' es un summary_table que hice para depurar y acelerar las cosas. Cada comentario, like y favorite se graba en realidad por separado. Parece que su consulta encontrará las publicaciones con la puntuación más alta. Estoy tratando de encontrar la publicación con la puntuación más alta por día en los últimos 18 días. No sé si tiene sentido. – user1070125

+0

Hola, ¿cómo es su estructura? Donde el registro comenta/favs/me gusta? Si es necesario, ¿puede cambiar las tablas? – Cristian

0

¡Guau! Difícil. Por ejemplo, siempre existe la posibilidad de lazos para max.

La siguiente solución crea una lista intermedia de max_scores del día, luego obtiene todas las publicaciones cuyos puntajes son iguales al máximo de su día. Devuelve vínculos, por lo que puede obtener dos filas para un día determinado. Le ruego que me disculpe por no poder probar esto, así que den sus comentarios, y estoy seguro de que podemos lograr que haga lo que necesita.

SELECT p.profile_id, p.post_id, p.pubdate_utc 
, DATE_FORMAT(p.pubdate_utc, '%d %b') AS post_date 
, DATE(p.pubdate_utc) AS mydate 
, (pp.comments + pp.likes + pp.favorites) AS score 
FROM posts p 
INNER JOIN posts_points pp ON p.post_id = pp.post_id 
INNER JOIN 
(
    SELECT p.pubdate_utc AS max_date, 
    (pp.comments + pp.likes + pp.favorites) AS max_score 
    FROM posts p2 
    INNER JOIN posts_points pp2 ON p2.post_id = pp2.post_id 
) m ON score = m.max_score 
AND mydate = m.max_date 
ORDER BY mydate DESC 
LIMIT 18; 
0

se puede ver esta consulta consulta .Inner en primer lugar se ha podido ir a esas filas que tienen post_id misma tanto en la tabla que suma (+ pp.comments pp.likes + pp.favorites) como marcador .Outer consulta se ha podido recuperar máximo puntuación y haciendo grupo por la fecha sabia ....

SELECT post_id, profile_id 
    , MAX(score) 
    , DATE_FORMAT(pubdate_utc, '%d %b') post_date 
    , DATE(pubdate_utc) as mydate 
FROM 
(
    SELECT p.profile_id, p.post_id, p.pubdate_utc 
     , (pp.comments + pp.likes + pp.favorites) AS score 
    FROM posts p 
    INNER JOIN posts_points pp ON p.post_id = pp.post_id 
) 
GROUP BY pubdate_utc 
ORDER BY pubdate_utc DESC 
2

Me encuentro con este problema todo el tiempo. Cuando MySQL ejecuta una función de agregado, para cualquier columna no agregada, simplemente extrae los primeros datos que ejecuta para ese grupo, ya sea desde la fila MAX o no. Entonces, lo que tienes que hacer es ordenar los datos en una consulta interna de tal manera que los máximos sean los primeros en sus grupos. Vea si esto funciona para usted:

SELECT t.post_id, 
     t.profile_id, 
     t.score, 
     t.pubdate_utc 
FROM (SELECT p.profile_id, 
      p.post_id, 
      p.pubdate_utc, 
      (pp.comments + pp.likes + pp.favorites) score 
     FROM posts p 
     JOIN posts_points pp ON p.post_id = pp.post_id 
     WHERE p.pubdate_utc >= DATE_ADD(DATE(NOW()), INTERVAL -17 DAY) 
     ORDER BY score DESC 
    ) t 
GROUP BY DATE(t.pubdate_utc) DESC 
; 

Tenga en cuenta que no utilizo la función MAX aquí. Ordenar por puntuación descendiendo y luego agrupando por fecha en la consulta externa obtendrá el puntaje más alto por fecha. También observe que puse la cláusula WHERE en la consulta interna. Las consultas internas como esta (algunas veces necesarias) no son muy eficientes, ya que no tienen índices para optimizar la consulta externa, así que asegúrese de que su conjunto de resultados interno sea lo más pequeño posible. Por último, observe GROUP BY DATE (t.pubdate_utc). Si no lo redujera a solo la información de fecha, habría mucho más de 18 resultados, ya que los tiempos también se cuentan.

Editar: Se ha cambiado a INTERVAL -17 DAY para dar hasta 18 resultados en lugar de 19.