Deze foutmelding
is meestal te wijten aan de definitie van uw kolommen en tabellen. Het betekent meestal dat er aan weerszijden van een gelijkteken verschillende sorteringen zijn. Wat u moet doen, is er een kiezen en die beslissing opnemen in uw vraag.
Het probleem met de sortering was hier in de CROSS JOIN van @prev_value waarvoor een expliciete sortering nodig was.
Ik heb ook de "row_number"-logica enigszins gewijzigd in een enkele cross-join en de if-logica naar het uiterste van de select-lijst verplaatst.
Hieronder worden enkele voorbeeldgegevens weergegeven. Er zijn voorbeeldgegevens nodig om query's mee te testen. Iedereen die uw vraag met werkende voorbeelden probeert te beantwoorden, heeft gegevens nodig. De reden dat ik het hier plaats, is tweeledig.
- zodat u elk resultaat begrijpt dat ik presenteer
- zodat u in de toekomst, wanneer u nog een SQL-gerelateerde vraag stelt, het belang van het verstrekken van gegevens begrijpt. Het is voor ons niet alleen handiger dat u dit doet. Als de vrager de voorbeeldgegevens verstrekt, zal de vrager het al begrijpen - het zal geen uitvinding zijn van een vreemde die een deel van hun tijd heeft besteed om te helpen.
Voorbeeldgegevens
Let op:sommige kolommen ontbreken in de tabellen, alleen de kolommen die in de tabeldetails zijn vermeld, zijn opgenomen.
Deze voorbeeldgegevens hebben 5 reacties op een enkele post (er worden geen likes geregistreerd)
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-standaardgedrag:2 rijen per postquery]
Dit was mijn eerste vraag, met enkele correcties. Ik heb de kolomvolgorde van de selectielijst gewijzigd, zodat u gemakkelijk enkele opmerkingengerelateerde gegevens kunt zien wanneer ik de resultaten presenteer. Bestudeer de resultaten die ze worden verstrekt, zodat u begrijpt wat de zoekopdracht zal doen. Kolommen voorafgegaan door # bestaan niet in de voorbeeldgegevens waarmee ik werk om redenen die ik al heb opgemerkt.
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
;
Bekijk een werkende demonstratie van deze query op SQLFiddle
| 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 |
Er zijn 2 RIJEN - zoals verwacht. Een rij voor de meest recente opmerking en een andere rij voor de volgende meest recente opmerking. Dit is normaal gedrag voor SQL en totdat een opmerking onder dit antwoord werd toegevoegd, zouden lezers van de vraag aannemen dat dit normale gedrag acceptabel zou zijn.
De vraag mist een duidelijk verwoord "verwacht resultaat".
[Optie 1:één rij per berichtquery, met TOT 2 opmerkingen, toegevoegde kolommen]
In een reactie hieronder werd onthuld dat je geen 2 rijen per bericht wilde en dit zou een gemakkelijke oplossing zijn. Nou, het is een beetje gemakkelijk MAAR er zijn opties en de opties worden bepaald door de gebruiker in de vorm van vereisten. ALS de vraag een "verwacht resultaat" had, dan zouden we weten welke optie we moeten kiezen. Desalniettemin is hier een optie
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
;
Zie de tweede query die werkt bij SQLFiddle
Resultaten van zoekopdracht 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 |
** Optie 2, voeg de meest recente opmerkingen samen tot één door komma's gescheiden lijst **
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
Bekijk deze derde zoekopdracht bij SQLFiddle
Resultaten van zoekopdracht 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 |
** Samenvatting **
Ik heb 3 query's gepresenteerd, elk toont alleen de 2 meest recente opmerkingen, maar elke query doet dat op een andere manier. De eerste zoekopdracht (standaardgedrag) toont 2 rijen voor elk bericht. Optie 2 voegt een kolom toe maar verwijdert de tweede rij. Optie 3 voegt de 2 meest recente opmerkingen samen.
Houd er rekening mee dat:
- De vraag mist tabeldefinities die alle kolommen dekken
- De vraag bevat geen voorbeeldgegevens, waardoor het moeilijker voor u is om de hier gepresenteerde resultaten te begrijpen, maar ook moeilijker voor ons om oplossingen voor te bereiden
- De vraag mist ook een definitief "verwacht resultaat" (de gewenste output) en dit heeft geleid tot verdere complexiteit bij het beantwoorden
Ik hoop dat de extra verstrekte informatie van enig nut zal zijn, en dat u inmiddels ook weet dat het normaal is dat SQL gegevens als meerdere rijen presenteert. Als je dat normale gedrag niet wilt, wees dan specifiek over wat je echt wilt in je vraag.
Naschrift. Om nog een subquery voor "follows" op te nemen, kunt u een vergelijkbare subquery gebruiken als degene die u al heeft. Het kan voor of na die subquery worden toegevoegd. Je kunt het ook in gebruik zien op sqlfiddle hier
LEFT JOIN (
SELECT
COUNT(*) FollowCNT
, IdOtherUser
FROM Activity
WHERE type = 'Follow'
GROUP BY
IdOtherUser
) F ON USERS.id = F.IdOtherUser
Hoewel het toevoegen van een andere subquery uw wens voor meer informatie kan oplossen, kan de algemene query langzamer worden in verhouding tot de groei van uw gegevens. Als je eenmaal hebt vastgesteld welke functionaliteit je echt nodig hebt, kan het de moeite waard zijn om te overwegen welke indexen je nodig hebt voor die tabellen. (Ik denk dat u geadviseerd wordt om dat advies apart te vragen, en als u dat doet, zorg er dan voor dat u 1. de volledige DDL van uw tabellen en 2. een uitlegplan van de query opneemt.)