Ten komunikat o błędzie
wynika to zazwyczaj z definicji Twoich kolumn i tabel. Zwykle oznacza to, że po obu stronach znaku równości znajdują się różne zestawienia. Musisz tylko wybrać jedną i uwzględnić tę decyzję w zapytaniu.
Problem z sortowaniem dotyczył tutaj CROSS JOIN @prev_value, które wymagało użycia jawnego sortowania.
Zmieniłem też nieco logikę "row_number" na pojedyncze sprzężenie krzyżowe i przeniosłem logikę if na skrajne granice listy wyboru.
Niektóre przykładowe dane są wyświetlane poniżej. Do testowania zapytań potrzebne są przykładowe dane. Każdy, kto spróbuje odpowiedzieć na Twoje pytanie za pomocą działających przykładów, będzie potrzebował danych. Powód, dla którego to tutaj zamieszczam, jest dwojaki.
- abyś zrozumiał każdy wynik, który przedstawiam
- aby w przyszłości, gdy zadasz kolejne pytanie związane z SQL, zrozumiałeś, jak ważne jest dostarczanie danych. To nie tylko dla nas wygodniejsze, jeśli to zrobisz. Jeśli pytający dostarczy przykładowe dane, to już je zrozumie – nie będzie to wymysł jakiejś nieznajomej, która poświęciła trochę czasu na pomoc.
Przykładowe dane
Należy pamiętać, że w tabelach brakuje niektórych kolumn, uwzględniono tylko kolumny określone w szczegółach tabeli.
Te przykładowe dane zawierają 5 komentarzy do jednego posta (nie są rejestrowane polubienia)
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') ;
[Standardowe zachowanie SQL:2 wiersze na zapytanie Post]
To było moje początkowe zapytanie, z pewnymi poprawkami. Zmieniłem kolejność kolumn na liście wyboru, aby łatwo zobaczyć niektóre dane związane z komentarzami, gdy przedstawię wyniki. Prosimy o zapoznanie się z podanymi wynikami, aby móc zrozumieć, co spowoduje zapytanie. Kolumny poprzedzone # nie istnieją w przykładowych danych, z którymi pracuję z powodów, o których już wspomniałem.
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
;
Zobacz działającą demonstrację tego zapytania w SQLFiddle
Wyniki :
| 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 |
Istnieją 2 RZĘDY - zgodnie z oczekiwaniami. Jeden wiersz na najnowszy komentarz i kolejne wiersze na kolejny najnowszy komentarz. Jest to normalne zachowanie SQL i dopóki nie zostanie dodany komentarz pod tą odpowiedzią, czytelnicy pytania zakładają, że to normalne zachowanie jest dopuszczalne.
W pytaniu brakuje jasno wyartykułowanego „oczekiwanego wyniku”.
[Opcja 1:jeden wiersz na zapytanie Post, DO 2 komentarzy, dodane kolumny]
W komentarzu poniżej ujawniono, że nie chcesz 2 wierszy na post i byłoby to łatwe rozwiązanie. Cóż, to trochę proste, ALE są opcje i opcje są dyktowane przez użytkownika w postaci wymagań. JEŚLI pytanie miałoby „oczekiwany wynik”, to wiedzielibyśmy, którą opcję wybrać. Niemniej jednak jest jedna opcja
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
;
Zobacz drugie zapytanie działające w SQLFiddle
| 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 |
** Opcja 2, połącz najnowsze komentarze w jedną listę oddzieloną przecinkami **
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
Zobacz trzecie zapytanie działające w SQLFiddle
| 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 |
** Podsumowanie **
Przedstawiłem 3 zapytania, każde pokazuje tylko 2 najnowsze komentarze, ale każde zapytanie robi to w inny sposób. Pierwsze zapytanie (zachowanie domyślne) wyświetli 2 wiersze na każdy post. Opcja 2 dodaje kolumnę, ale usuwa drugi wiersz. Opcja 3 łączy 2 najnowsze komentarze.
Należy pamiętać, że:
- W pytaniu brakuje definicji tabel obejmujących wszystkie kolumny
- W pytaniu brakuje jakichkolwiek przykładowych danych, co utrudnia zrozumienie prezentowanych tu wyników, ale także utrudnia nam przygotowanie rozwiązań
- Pytaniu brakuje również ostatecznego „oczekiwanego wyniku” (pożądany wynik), co prowadzi do dalszej złożoności odpowiedzi
Mam nadzieję, że te dodatkowe informacje okażą się przydatne i że już wiesz, że SQL przedstawianie danych w wielu wierszach jest normalne. Jeśli nie chcesz tego normalnego zachowania, określ dokładnie, czego naprawdę chcesz w swoim pytaniu.
Postscriptum. Aby dołączyć jeszcze jedno podzapytanie dla „obserwacji”, możesz użyć podzapytania podobnego do tego, które już masz. Może być dodany przed lub po tym podzapytaniu. Możesz go również zobaczyć w użyciu w sqlfiddle tutaj
LEFT JOIN (
SELECT
COUNT(*) FollowCNT
, IdOtherUser
FROM Activity
WHERE type = 'Follow'
GROUP BY
IdOtherUser
) F ON USERS.id = F.IdOtherUser
Chociaż dodanie kolejnego podzapytania może rozwiązać Twoje pragnienie uzyskania większej ilości informacji, ogólne zapytanie może być wolniejsze proporcjonalnie do wzrostu danych. Po ustaleniu funkcjonalności, której naprawdę potrzebujesz, warto zastanowić się, jakich indeksów potrzebujesz w tych tabelach. (Uważam, że zaleca się, aby poprosić o tę poradę osobno, a jeśli to zrobisz, upewnij się, że zawierasz 1. pełne DDL swoich tabel i 2. wyjaśnij plan zapytania.)