Diese Fehlermeldung
liegt typischerweise an der Definition Ihrer Spalten und Tabellen. Dies bedeutet normalerweise, dass auf beiden Seiten eines Gleichheitszeichens unterschiedliche Sortierungen vorhanden sind. Sie müssen nur eine auswählen und diese Entscheidung in Ihre Anfrage aufnehmen.
Das Kollationsproblem lag hier im CROSS JOIN von @prev_value, der eine explizite Kollatierung benötigte, um verwendet zu werden.
Ich habe auch die "row_number"-Logik leicht in einen einzelnen Kreuzjoin geändert und die if-Logik an die äußersten Enden der Auswahlliste verschoben.
Einige Beispieldaten werden unten angezeigt. Beispieldaten werden zum Testen von Abfragen benötigt. Jeder, der versucht, Ihre Frage mit funktionierenden Beispielen zu beantworten, benötigt Daten. Der Grund, warum ich es hier einfüge, ist zweierlei.
- damit Sie jedes von mir präsentierte Ergebnis verstehen werden
- damit Sie in Zukunft verstehen, wie wichtig es ist, Daten bereitzustellen, wenn Sie eine andere SQL-bezogene Frage stellen. Das ist nicht nur für uns bequemer. Wenn der Fragesteller die Beispieldaten bereitstellt, wird der Fragesteller sie bereits verstehen - es wird keine Erfindung eines Fremden sein, der einen Teil seiner Zeit darauf verwendet hat, zu helfen.
Beispieldaten
Bitte beachten Sie, dass einige Spalten in den Tabellen fehlen, es wurden nur die in den Tabellendetails angegebenen Spalten aufgenommen.
Diese Beispieldaten enthalten 5 Kommentare zu einem einzelnen Beitrag (es werden keine „Gefällt mir“-Angaben aufgezeichnet)
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-Standardverhalten:2 Zeilen pro Post-Abfrage]
Dies war meine erste Anfrage, mit einigen Korrekturen. Ich habe die Spaltenreihenfolge der Auswahlliste geändert, sodass Sie einige kommentarbezogene Daten leicht sehen können, wenn ich die Ergebnisse präsentiere. Bitte studieren Sie die bereitgestellten Ergebnisse, damit Sie verstehen, was die Abfrage bewirken wird. Spalten mit vorangestelltem # sind in den Beispieldaten, mit denen ich arbeite, aus Gründen, die ich bereits erwähnt habe, nicht vorhanden.
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
;
Siehe eine funktionierende Demonstration dieser Abfrage bei 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 |
Es gibt 2 REIHEN - wie erwartet. Eine Zeile für den neuesten Kommentar und eine weitere Zeile für den nächstneuesten Kommentar. Dies ist ein normales Verhalten für SQL und bis ein Kommentar unter dieser Antwort hinzugefügt wurde, würden die Leser der Frage davon ausgehen, dass dieses normale Verhalten akzeptabel wäre.
Der Frage fehlt ein klar artikuliertes "erwartetes Ergebnis".
[Option 1:Eine Zeile pro Post-Abfrage, mit BIS ZU 2 Kommentaren, hinzugefügten Spalten]
In einem Kommentar unten wurde offenbart, dass Sie keine 2 Zeilen pro Beitrag wollten und dies eine einfache Lösung wäre. Nun, es ist irgendwie einfach, ABER es gibt Optionen und die Optionen werden vom Benutzer in Form von Anforderungen diktiert. Wenn die Frage ein "erwartetes Ergebnis" hätte, wüssten wir, welche Option zu wählen ist. Nichtsdestotrotz ist hier eine Option
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
;
Siehe die zweite Abfrage, die bei SQLFiddle funktioniert
| 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 |
** Option 2, die neuesten Kommentare in einer einzigen, durch Kommas getrennten Liste verketten **
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
Siehe diese dritte Abfrage, die bei SQLFiddle funktioniert
| 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 |
** Zusammenfassung **
Ich habe 3 Abfragen präsentiert, jede zeigt nur die 2 neuesten Kommentare, aber jede Abfrage tut dies auf andere Weise. Die erste Abfrage (Standardverhalten) zeigt 2 Zeilen für jeden Beitrag an. Option 2 fügt eine Spalte hinzu, entfernt aber die zweite Zeile. Option 3 verkettet die 2 neuesten Kommentare.
Bitte beachten Sie Folgendes:
- Der Frage fehlen Tabellendefinitionen, die alle Spalten abdecken
- Der Frage fehlen Beispieldaten, was es für Sie schwieriger macht, die hier präsentierten Ergebnisse zu verstehen, aber auch für uns schwieriger, Lösungen vorzubereiten
- Der Frage fehlt auch ein endgültiges "erwartetes Ergebnis" (das gewünschte Ergebnis), was zu einer weiteren Komplexität der Beantwortung geführt hat
Ich hoffe, dass die zusätzlichen bereitgestellten Informationen von Nutzen sind und dass Sie inzwischen auch wissen, dass es für SQL normal ist, Daten als mehrere Zeilen darzustellen. Wenn Sie dieses normale Verhalten nicht möchten, geben Sie bitte in Ihrer Frage genau an, was Sie wirklich wollen.
Nachschrift. Um eine weitere Unterabfrage für "folgt" einzufügen, können Sie eine ähnliche Unterabfrage wie die bereits vorhandene verwenden. Sie kann vor oder nach dieser Unterabfrage hinzugefügt werden. Sie können es auch bei sqlfiddle hier im Einsatz sehen
LEFT JOIN (
SELECT
COUNT(*) FollowCNT
, IdOtherUser
FROM Activity
WHERE type = 'Follow'
GROUP BY
IdOtherUser
) F ON USERS.id = F.IdOtherUser
Während das Hinzufügen einer weiteren Unterabfrage Ihren Wunsch nach mehr Informationen beseitigen kann, kann die Gesamtabfrage proportional zum Wachstum Ihrer Daten langsamer werden. Sobald Sie sich für die Funktionalität entschieden haben, die Sie wirklich benötigen, kann es sich lohnen, darüber nachzudenken, welche Indizes Sie für diese Tabellen benötigen. (Ich glaube, Sie sollten diesen Rat separat anfordern, und wenn Sie dies tun, stellen Sie sicher, dass Sie 1. die vollständige DDL Ihrer Tabellen und 2. einen Erklärungsplan der Abfrage beifügen.)