sql >> Database teknologi >  >> RDS >> Mysql

MYSQL-forespørgsel - Få seneste kommentar relateret til indlægget

Denne fejlmeddelelse

skyldes typisk definitionen af ​​dine kolonner og tabeller. Det betyder normalt, at der på hver side af et lighedstegn er forskellige sammenstillinger. Det, du skal gøre, er at vælge en og inkludere den beslutning i din forespørgsel.

Sorteringsproblemet her var i CROSS JOIN af @prev_value, som skulle bruge en eksplicit sortering for at blive brugt.

Jeg har også lidt ændret "row_number"-logikken til en enkelt krydssammenføjning og flyttet if-logikken til yderpunkterne af den valgte liste.

Nogle eksempeldata vises nedenfor. Eksempeldata er nødvendige for at teste forespørgsler med. Enhver, der forsøger at besvare dit spørgsmål med arbejdseksempler, har brug for data. Grunden til, at jeg medtager det her, er todelt.

  1. så du forstår ethvert resultat, jeg præsenterer
  2. så, at du i fremtiden forstår vigtigheden af ​​at levere data, når du stiller et andet SQL-relateret spørgsmål. Det er ikke kun mere bekvemt for os, at du gør dette. Hvis spørgeren giver prøvedataene, vil spørgeren allerede forstå det - det vil ikke være en opfindelse af en fremmed, der har brugt noget af deres tid på at hjælpe.

Eksempel på data

Bemærk venligst, at nogle kolonner mangler i tabellerne, kun de kolonner, der er angivet i tabeldetaljerne, er inkluderet.

Denne eksempeldata har 5 kommentarer til et enkelt opslag (ingen likes registreres)

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') ;
 

[SQL Standard-adfærd:2 rækker pr. Post-forespørgsel]

Dette var min første forespørgsel, med nogle rettelser. Jeg ændrede kolonnerækkefølgen på udvalgslisten, så du nemt kan se nogle kommentarrelaterede data, når jeg præsenterer resultaterne. Læs venligst disse resultater, de er leveret, så du kan forstå, hvad forespørgslen vil gøre. Kolonner med # foran findes ikke i de eksempeldata, jeg arbejder med, af årsager, som jeg allerede har noteret.

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
      ;
      
      
 

Se en fungerende demonstration af denne forespørgsel på SQLFiddle

Resultater :

| 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 |

Der er 2 RÆKKER - som forventet. En række for den seneste kommentar, og en anden række for den næste seneste kommentar. Dette er normal adfærd for SQL, og indtil en kommentar blev tilføjet under dette svar, ville læsere af spørgsmålet antage, at denne normale adfærd ville være acceptabel.

Spørgsmålet mangler et klart formuleret "forventet resultat".

[Valgmulighed 1:En række pr. indlægsforespørgsel, med OP TIL 2 kommentarer, tilføjede kolonner]

I en kommentar nedenfor blev det afsløret, at du ikke ønskede 2 rækker pr. indlæg, og dette ville være en nem løsning. Det er på en måde nemt, MEN der er muligheder, og mulighederne er dikteret af brugeren i form af krav. HVIS spørgsmålet havde et "forventet resultat", ville vi vide, hvilken mulighed vi skulle vælge. Ikke desto mindre er her én mulighed

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
      ;
 

Se den anden forespørgsel, der arbejder på SQLFiddle

Resultater af forespørgsel 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 |

** Mulighed 2, sammenkæd de seneste kommentarer til en enkelt kommasepareret liste **

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
      
 

Se denne tredje forespørgsel, der fungerer hos SQLFiddle

Resultater af forespørgsel 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 |

** Resumé **

Jeg har præsenteret 3 forespørgsler, hver viser kun de 2 seneste kommentarer, men hver forespørgsel gør det på en anden måde. Den første forespørgsel (standardadfærd) vil vise 2 rækker for hvert indlæg. Mulighed 2 tilføjer en kolonne, men fjerner den anden række. Mulighed 3 sammenkæder de 2 seneste kommentarer.

Bemærk venligst at:

  • Spørgsmålet mangler tabeldefinitioner, der dækker alle kolonner
  • Spørgsmålet mangler nogen prøvedata, hvilket gør det sværere for dig at forstå eventuelle resultater præsenteret her, men også sværere for os at udarbejde løsninger
  • Spørgsmålet mangler også et endegyldigt "forventet resultat" (det ønskede output), og dette har ført til yderligere kompleksitet i besvarelsen

Jeg håber, at de yderligere angivne oplysninger vil være til nogen nytte, og at du efterhånden også ved, at det er normalt for SQL at præsentere data som flere rækker. Hvis du ikke ønsker den normale adfærd, bedes du være specifik om, hvad du virkelig ønsker i dit spørgsmål.

Efterskrift. For at inkludere endnu en underforespørgsel til "følger" kan du bruge en lignende underforespørgsel som den, du allerede har. Det kan tilføjes før eller efter denne underforespørgsel. Du kan også se det i brug på sqlfiddle her

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

Mens tilføjelse af endnu en underforespørgsel kan løse dit ønske om mere information, kan den overordnede forespørgsel blive langsommere i forhold til væksten i dine data. Når du har sat dig fast på den funktionalitet, du virkelig har brug for, kan det være umagen værd at overveje, hvilke indekser du har brug for på disse borde. (Jeg tror, ​​at du vil blive rådet til at bede om det råd separat, og hvis du gør det, skal du sørge for at inkludere 1. den fulde DDL for dine tabeller og 2. en forklarende plan for forespørgslen.)



  1. Rails:Tving tom streng til NULL i databasen

  2. Hvorfor bruger MySQL ikke den primære nøgle på JOIN plus ORDER?

  3. Brug af union og orden efter klausul i mysql

  4. Kan SQL Server Express LocalDB tilsluttes eksternt?