sql >> Base de Datos >  >> RDS >> Mysql

Consulta MYSQL:obtenga el último comentario relacionado con la publicación

Este mensaje de error

generalmente se debe a la definición de sus columnas y tablas. Por lo general, significa que a cada lado de un signo igual hay diferentes intercalaciones. Lo que debes hacer es elegir uno e incluir esa decisión en tu consulta.

El problema de intercalación aquí estaba en CROSS JOIN de @prev_value que necesitaba una intercalación explícita para ser utilizada.

También cambié ligeramente la lógica "row_number" a una sola unión cruzada y moví la lógica if a los extremos de la lista de selección.

Algunos datos de muestra se muestran a continuación. Se necesitan datos de muestra para probar las consultas. Cualquiera que intente responder a su pregunta con ejemplos de trabajo necesitará datos. La razón por la que lo incluyo aquí es doble.

  1. para que entienda cualquier resultado que presente
  2. para que en el futuro, cuando haga otra pregunta relacionada con SQL, comprenda la importancia de proporcionar datos. No solo es más conveniente para nosotros que usted haga esto. Si el autor de la pregunta proporciona los datos de muestra, entonces el autor de la pregunta ya lo entenderá; no será una invención de un extraño que ha dedicado parte de su tiempo a ayudar.

Datos de muestra

Tenga en cuenta que faltan algunas columnas en las tablas, solo se han incluido las columnas especificadas en los detalles de la tabla.

Estos datos de muestra tienen 5 comentarios en una sola publicación (no se registran Me gusta)

CREATE TABLE Posts 
(
`id` int, 
`uuid` varchar(7) collate utf8_unicode_ci,
`imageLink` varchar(9) collate utf8_unicode_ci, 
`date` datetime
 );
    
INSERT INTO Posts(`id`, `uuid`, `imageLink`, `date`)
VALUES
(145, 'abcdefg', 'blah blah', '2016-10-10 00:00:00') ;

CREATE TABLE   USERS
(
`id` int, 
`username` varchar(15) collate utf8_unicode_ci,
 `profileImage` varchar(12) collate utf8_unicode_ci,
 `date` datetime
) ;
        
INSERT INTO     USERS(`id`, `username`, `profileImage`, `date`)
VALUES
(145, 'used_by_already', 'blah de blah', '2014-01-03 00:00:00') ;
    
    
CREATE TABLE Activity
(
`id` int, 
`uuid` varchar(4) collate utf8_unicode_ci, 
`uuidPost` varchar(7) collate utf8_unicode_ci,
 `type` varchar(40) collate utf8_unicode_ci, 
`commentText` varchar(11) collate utf8_unicode_ci, `date` datetime
) ;
        
INSERT INTO Activity (`id`, `uuid`, `uuidPost`, `type`, `commentText`, `date`)
 VALUES
(345, 'a100', 'abcdefg', 'comment', 'lah lha ha', '2016-07-05 00:00:00'),
(456, 'a101', 'abcdefg', 'comment', 'lah lah lah', '2016-07-06 00:00:00'),
(567, 'a102', 'abcdefg', 'comment', 'lha lha ha', '2016-07-07 00:00:00'),
(678, 'a103', 'abcdefg', 'comment', 'ha lah lah', '2016-07-08 00:00:00'),
(789, 'a104', 'abcdefg', 'comment', 'hla lah lah', '2016-07-09 00:00:00') ;

[Comportamiento estándar de SQL:2 filas por consulta de publicación]

Esta fue mi consulta inicial, con algunas correcciones. Cambié el orden de las columnas de la lista de selección para que pueda ver fácilmente algunos datos relacionados con los comentarios cuando presente los resultados. Estudie los resultados que se proporcionan para que pueda comprender lo que hará la consulta. Las columnas precedidas por # no existen en los datos de muestra con los que estoy trabajando por las razones que ya he indicado.

SELECT
      Posts.id
    , Posts.uuid
    , rcom.uuidPost
    , rcom.commentText
    , rcom.`date` commentDate 
    #, Posts.caption
    #, Posts.path
    , Posts.`date`
    , USERS.id
    , USERS.username
    #, USERS.fullname
    , USERS.profileImage
    , COALESCE(A.LikeCNT, 0) num_likes
FROM Posts
INNER JOIN USERS ON Posts.id = 145
            AND USERS.id = 145
LEFT JOIN (
          SELECT
                COUNT(A.uuidPost) LikeCNT
              , A.UUIDPost
          FROM Activity A
          WHERE type = 'like'
          GROUP BY
                A.UUIDPOST
          ) A ON A.UUIDPost = Posts.uuid 
LEFT JOIN (
      SELECT
            @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
          , commentText
          , uuidPost
          , `date`
          , @prev_value := UUIDPOST
      FROM Activity
      CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci  ) xy
      WHERE type = 'comment'
      ORDER BY
            uuidPost
          , `date` DESC
      ) rcom ON rcom.uuidPost  = Posts.UUID
            AND rcom.row_number <= 2
ORDER BY
      posts.`date` DESC
      ;
      
      

Vea una demostración funcional de esta consulta en SQLFiddle

Resultados :

|  id |    uuid | uuidPost | commentText |                   date |                      date |  id |        username | profileImage | num_likes |
|-----|---------|----------|-------------|------------------------|---------------------------|-----|-----------------|--------------|-----------|
| 145 | abcdefg |  abcdefg | hla lah lah | July, 09 2016 00:00:00 | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |
| 145 | abcdefg |  abcdefg |  ha lah lah | July, 08 2016 00:00:00 | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |

Hay 2 FILAS, como se esperaba. Una fila para el comentario más reciente y otra fila para el siguiente comentario más reciente. Este es un comportamiento normal para SQL y hasta que se agregue un comentario en esta respuesta, los lectores de la pregunta asumirán que este comportamiento normal sería aceptable.

La pregunta carece de un "resultado esperado" claramente articulado.

[Opción 1:una fila por consulta de publicación, con HASTA 2 comentarios, columnas añadidas]

En un comentario a continuación, se reveló que no quería 2 filas por publicación y que esto sería una solución fácil. Bueno, es fácil PERO hay opciones y las opciones las dicta el usuario en forma de requisitos. SI la pregunta tuviera un "resultado esperado", entonces sabríamos qué opción elegir. No obstante, aquí hay una opción

SELECT
      Posts.id
    , Posts.uuid
    , max(case when rcom.row_number = 1 then rcom.commentText end) Comment_one
    , max(case when rcom.row_number = 2 then rcom.commentText end) Comment_two
    #, Posts.caption
    #, Posts.path
    , Posts.`date`
    , USERS.id
    , USERS.username
    #, USERS.fullname
    , USERS.profileImage
    , COALESCE(A.LikeCNT, 0) num_likes
FROM Posts
INNER JOIN USERS ON Posts.id = 145
            AND USERS.id = 145
LEFT JOIN (
          SELECT
                COUNT(A.uuidPost) LikeCNT
              , A.UUIDPost
          FROM Activity A
          WHERE type = 'like'
          GROUP BY
                A.UUIDPOST
          ) A ON A.UUIDPost = Posts.uuid 
LEFT JOIN (
      SELECT
            @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
          , commentText
          , uuidPost
          , `date`
          , @prev_value := UUIDPOST
      FROM Activity
      CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci  ) xy
      WHERE type = 'comment'
      ORDER BY
            uuidPost
          , `date` DESC
      ) rcom ON rcom.uuidPost  = Posts.UUID
            AND rcom.row_number <= 2
GROUP BY
      Posts.id
    , Posts.uuid
    #, Posts.caption
    #, Posts.path
    , Posts.`date`
    , USERS.id
    , USERS.username
    #, USERS.fullname
    , USERS.profileImage
    , COALESCE(A.LikeCNT, 0)
ORDER BY
      posts.`date` DESC
      ;

Vea la segunda consulta trabajando en SQLFiddle

Resultados de la consulta 2 :

|  id |    uuid | Comment_one | Comment_two |                      date |  id |        username | profileImage | num_likes |
|-----|---------|-------------|-------------|---------------------------|-----|-----------------|--------------|-----------|
| 145 | abcdefg | hla lah lah |  ha lah lah | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |

** Opción 2, concatenar los comentarios más recientes en una sola lista separada por comas **

SELECT
      Posts.id
    , Posts.uuid
    , group_concat(rcom.commentText) Comments_two_concatenated
    #, Posts.caption
    #, Posts.path
    , Posts.`date`
    , USERS.id
    , USERS.username
    #, USERS.fullname
    , USERS.profileImage
    , COALESCE(A.LikeCNT, 0) num_likes
FROM Posts
INNER JOIN USERS ON Posts.id = 145
            AND USERS.id = 145
LEFT JOIN (
          SELECT
                COUNT(A.uuidPost) LikeCNT
              , A.UUIDPost
          FROM Activity A
          WHERE type = 'like'
          GROUP BY
                A.UUIDPOST
          ) A ON A.UUIDPost = Posts.uuid 
LEFT JOIN (
      SELECT
            @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
          , commentText
          , uuidPost
          , `date`
          , @prev_value := UUIDPOST
      FROM Activity
      CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci  ) xy
      WHERE type = 'comment'
      ORDER BY
            uuidPost
          , `date` DESC
      ) rcom ON rcom.uuidPost  = Posts.UUID
            AND rcom.row_number <= 2
GROUP BY
      Posts.id
    , Posts.uuid
    #, Posts.caption
    #, Posts.path
    , Posts.`date`
    , USERS.id
    , USERS.username
    #, USERS.fullname
    , USERS.profileImage
    , COALESCE(A.LikeCNT, 0)
ORDER BY
      posts.`date` DESC
      

Vea esta tercera consulta trabajando en SQLFiddle

Resultados de la consulta 3 :

|  id |    uuid | Comments_two_concatenated |                      date |  id |        username | profileImage | num_likes |
|-----|---------|---------------------------|---------------------------|-----|-----------------|--------------|-----------|
| 145 | abcdefg |    hla lah lah,ha lah lah | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |

** Resumen **

He presentado 3 consultas, cada una muestra solo los 2 comentarios más recientes, pero cada consulta lo hace de manera diferente. La primera consulta (comportamiento predeterminado) mostrará 2 filas para cada publicación. La opción 2 agrega una columna pero elimina la segunda fila. La opción 3 concatena los 2 comentarios más recientes.

Tenga en cuenta que:

  • La pregunta carece de definiciones de tabla que cubran todas las columnas
  • La pregunta carece de datos de muestra, lo que hace que sea más difícil para usted comprender los resultados presentados aquí, pero también más difícil para nosotros preparar soluciones
  • La pregunta también carece de un "resultado esperado" definitivo (el resultado deseado) y esto ha llevado a una mayor complejidad en la respuesta

Espero que la información adicional proporcionada sea de alguna utilidad y que, a estas alturas, también sepa que es normal que SQL presente datos en varias filas. Si no desea ese comportamiento normal, sea específico sobre lo que realmente desea en su pregunta.

Posdata. Para incluir otra subconsulta para "sigue", puede usar una subconsulta similar a la que ya tiene. Puede agregarse antes o después de esa subconsulta. También puede verlo en uso en sqlfiddle aquí

LEFT JOIN (
          SELECT
                COUNT(*) FollowCNT
              , IdOtherUser
          FROM Activity
          WHERE type = 'Follow'
          GROUP BY
                IdOtherUser
          ) F ON USERS.id = F.IdOtherUser

Si bien agregar otra subconsulta puede resolver su deseo de obtener más información, la consulta general puede volverse más lenta en proporción al crecimiento de sus datos. Una vez que se haya decidido por la funcionalidad que realmente necesita, puede valer la pena considerar qué índices necesita en esas tablas. (Creo que se le recomendaría que pida ese consejo por separado y, si lo hace, asegúrese de incluir 1. el DDL completo de sus tablas y 2. un plan explicativo de la consulta).