Kolejność MySQL według grupuj według

243

Można tu znaleźć wiele podobnych pytań, ale nie sądzę, aby jakakolwiek odpowiedź na to pytanie była odpowiednia.

Będę kontynuować od najpopularniejszego pytania i użyję ich przykładu, jeśli to w porządku.

W tym przypadku zadaniem jest uzyskanie najnowszego postu dla każdego autora w bazie danych.

Przykładowe zapytanie daje bezużyteczne wyniki, ponieważ nie zawsze jest to ostatni zwracany post.

SELECT wp_posts.* FROM wp_posts
    WHERE wp_posts.post_status='publish'
    AND wp_posts.post_type='post'
    GROUP BY wp_posts.post_author           
    ORDER BY wp_posts.post_date DESC

Obecna akceptowana odpowiedź to

SELECT
    wp_posts.*
FROM wp_posts
WHERE
    wp_posts.post_status='publish'
    AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author
HAVING wp_posts.post_date = MAX(wp_posts.post_date) <- ONLY THE LAST POST FOR EACH AUTHOR
ORDER BY wp_posts.post_date DESC

Niestety ta odpowiedź jest prosta i błędna, aw wielu przypadkach daje mniej stabilne wyniki niż pierwotne zapytanie.

Moim najlepszym rozwiązaniem jest użycie podzapytania formularza

SELECT wp_posts.* FROM 
(
    SELECT * 
    FROM wp_posts
    ORDER BY wp_posts.post_date DESC
) AS wp_posts
WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author 

Moje pytanie jest więc proste: czy w ogóle można zamówić wiersze przed grupowaniem bez uciekania się do podzapytania?

Edycja : To pytanie było kontynuacją innego pytania, a specyfika mojej sytuacji jest nieco inna. Możesz (i powinieneś) założyć, że istnieje również wp_posts.id, który jest unikalnym identyfikatorem dla tego konkretnego postu.

Rob Forrest
źródło
2
Jak wspomniałeś w komentarzach do podanych odpowiedzi, możliwe, że niektóre posty będą miały ten sam znacznik czasu. Jeśli tak, proszę podać przykład z danymi i oczekiwanym rezultatem. I opisz, dlaczego oczekujesz tego wyniku. post_authori post_datenie wystarczą, aby uzyskać unikalny wiersz, więc musi być więcej, aby uzyskać unikalny wiersz napost_author
Sir Rufo
@ SirRufo Masz rację, dodałem edycję dla ciebie.
Rob Forrest,
There are plenty of similar questions to be found on here but I don't think that any answer the question adequately.Po to są nagrody.
Wyścigi lekkości na orbicie
@LightnessRacesinOrbit, jeśli bieżące pytanie ma już zaakceptowaną odpowiedź, która moim zdaniem jest błędna, co sugerowalibyście zrobić?
Rob Forrest,
1
Zastanawiasz się, dlaczego zaakceptowałeś odpowiedź, która korzysta z podzapytania - kiedy twoje pytanie wyraźnie brzmi ... „„ Czy w ogóle można zamówić wiersze przed grupowaniem bez uciekania się do podzapytania? ”???
TV-C-15,

Odpowiedzi:

373

Korzystanie ORDER BYz podzapytania nie jest najlepszym rozwiązaniem tego problemu.

Najlepszym rozwiązaniem, aby uzyskać max(post_date)autor, jest użycie podzapytania, aby zwrócić maksymalną datę, a następnie dołączyć ją do tabeli zarówno w post_authordniu maksymalnym, jak i maksymalnym.

Rozwiązaniem powinno być:

SELECT p1.* 
FROM wp_posts p1
INNER JOIN
(
    SELECT max(post_date) MaxPostDate, post_author
    FROM wp_posts
    WHERE post_status='publish'
       AND post_type='post'
    GROUP BY post_author
) p2
  ON p1.post_author = p2.post_author
  AND p1.post_date = p2.MaxPostDate
WHERE p1.post_status='publish'
  AND p1.post_type='post'
order by p1.post_date desc

Jeśli masz następujące przykładowe dane:

CREATE TABLE wp_posts
    (`id` int, `title` varchar(6), `post_date` datetime, `post_author` varchar(3))
;

INSERT INTO wp_posts
    (`id`, `title`, `post_date`, `post_author`)
VALUES
    (1, 'Title1', '2013-01-01 00:00:00', 'Jim'),
    (2, 'Title2', '2013-02-01 00:00:00', 'Jim')
;

Podkwerenda zwróci maksymalną datę i autora:

MaxPostDate | Author
2/1/2013    | Jim

Następnie, ponieważ dołączasz to z powrotem do tabeli, w przypadku obu wartości zwrócisz pełne szczegóły tego postu.

Zobacz SQL Fiddle with Demo .

Aby rozwinąć moje komentarze na temat korzystania z podzapytania w celu dokładnego zwrócenia tych danych.

MySQL nie zmusza cię do GROUP BYkażdej kolumny, którą umieszczasz na SELECTliście. W rezultacie, jeśli tylko GROUP BYjedna kolumna zwróci łącznie 10 kolumn, nie ma gwarancji, że pozostałe wartości kolumn należące do tej, post_authorktóra zostanie zwrócona. Jeśli kolumna nie znajduje się w GROUP BYMySQL, wybiera jaką wartość należy zwrócić.

Użycie podzapytania z funkcją agregującą zagwarantuje, że poprawny autor i post będą zwracane za każdym razem.

Na marginesie, podczas gdy MySQL pozwala na użycie ORDER BYw podzapytaniu i pozwala zastosować GROUP BYdo nie każdej kolumny na SELECTliście, to zachowanie nie jest dozwolone w innych bazach danych, w tym SQL Server.

Taryn
źródło
4
Widzę, co tam zrobiłeś, ale to po prostu zwraca datę utworzenia ostatniego postu, a nie cały wiersz dla tego ostatniego postu.
Rob Forrest
1
@RobForrest to właśnie robi łączenie. Zwracasz ostatnią datę postu w podzapytaniu według autora, a następnie ponownie dołączasz do swoich wp_postsw obu kolumnach, aby uzyskać pełny wiersz.
Taryn
7
@RobForrest Po jednym, gdy zastosujesz GROUP BYtylko jedną kolumnę, nie ma gwarancji, że wartości w pozostałych kolumnach będą konsekwentnie poprawne. Niestety, MySQL pozwala na działanie tego typu WYBORU / GRUPOWANIA, czego nie robią inne produkty. Po ORDER BYdrugie , składnia użycia an w podzapytaniu, gdy jest dozwolona w MySQL, nie jest dozwolona w innych produktach bazodanowych, w tym SQL Server. Powinieneś użyć rozwiązania, które zwróci właściwy wynik za każdym razem, gdy zostanie wykonane.
Taryn
2
Dla skalowania związek INDEX(post_author, post_date)jest ważny.
Rick James
1
@ jtcotton63 To prawda, ale jeśli wpiszesz post_idswoje wewnętrzne zapytanie, technicznie powinieneś je również pogrupować, co najprawdopodobniej wypaczy Twoje wyniki.
Taryn
20

Twoje rozwiązanie korzysta z rozszerzenia klauzuli GROUP BY , która pozwala grupować według niektórych pól (w tym przypadku po prostu post_author):

GROUP BY wp_posts.post_author

i wybierz niezagregowane kolumny:

SELECT wp_posts.*

które nie są wymienione w grupie według klauzuli lub które nie są używane w funkcji agregującej (MIN, MAX, COUNT itp.).

Prawidłowe użycie rozszerzenia klauzuli GROUP BY

Jest to przydatne, gdy wszystkie wartości niezagregowanych kolumn są równe dla każdego wiersza.

Załóżmy na przykład, że masz stół GardensFlowers( namew ogrodzie, flowerktóry rośnie w ogrodzie):

INSERT INTO GardensFlowers VALUES
('Central Park',       'Magnolia'),
('Hyde Park',          'Tulip'),
('Gardens By The Bay', 'Peony'),
('Gardens By The Bay', 'Cherry Blossom');

i chcesz wydobyć wszystkie kwiaty, które rosną w ogrodzie, w którym rośnie wiele kwiatów. Następnie musisz użyć podzapytania, na przykład możesz użyć tego:

SELECT GardensFlowers.*
FROM   GardensFlowers
WHERE  name IN (SELECT   name
                FROM     GardensFlowers
                GROUP BY name
                HAVING   COUNT(DISTINCT flower)>1);

Jeśli zamiast tego musisz wyodrębnić wszystkie kwiaty, które są jedynymi kwiatami w garderobie, możesz po prostu zmienić warunek HAVING na HAVING COUNT(DISTINCT flower)=1, ale MySql pozwala również na użycie tego:

SELECT   GardensFlowers.*
FROM     GardensFlowers
GROUP BY name
HAVING   COUNT(DISTINCT flower)=1;

bez podkwerendy, niestandardowy SQL, ale prostszy.

Niepoprawne użycie rozszerzenia klauzuli GROUP BY

Ale co się stanie, jeśli wybierzesz niezagregowane kolumny, które nie są równe dla każdego wiersza? Jaką wartość wybiera MySql dla tej kolumny?

Wygląda na to, że MySql zawsze wybiera PIERWSZĄ wartość, na jaką napotyka.

Aby upewnić się, że pierwsza napotkana wartość jest dokładnie taką, jakiej potrzebujesz, musisz zastosować a GROUP BYdo uporządkowanego zapytania, stąd potrzeba użycia podzapytania. Nie możesz tego zrobić inaczej.

Zakładając, że MySql zawsze wybiera pierwszy napotkany wiersz, poprawnie sortujesz wiersze przed GROUP BY. Ale niestety, jeśli dokładnie przeczytasz dokumentację, zauważysz, że to założenie nie jest prawdziwe.

Podczas wybierania niezagregowanych kolumn, które nie zawsze są takie same, MySql może wybrać dowolną wartość, więc wynikowa wartość, którą faktycznie pokazuje, jest nieokreślona .

Widzę, że ta sztuczka polegająca na uzyskaniu pierwszej wartości niezagregowanej kolumny jest często używana i zwykle / prawie zawsze działa, czasem jej używam (na własne ryzyko). Ale ponieważ nie jest to udokumentowane, nie możesz polegać na tym zachowaniu.

Ten link (dzięki ypercube!) Sztuczka GROUP BY została zoptymalizowana, pokazuje sytuację, w której to samo zapytanie zwraca różne wyniki między MySql a MariaDB, prawdopodobnie z powodu innego silnika optymalizacji.

Więc jeśli ta sztuczka się sprawdzi, to tylko kwestia szczęścia.

Akceptowane odpowiedź na inne pytanie wygląda źle do mnie:

HAVING wp_posts.post_date = MAX(wp_posts.post_date)

wp_posts.post_datejest niezagregowaną kolumną, a jej wartość zostanie oficjalnie nieokreślona, ​​ale prawdopodobnie będzie to pierwsza post_datenapotkana. Ale ponieważ sztuczka GROUP BY jest stosowana do nieuporządkowanej tabeli, nie jest pewne, która jest pierwsza post_datenapotkana.

Prawdopodobnie zwróci posty, które są jedynymi postami jednego autora, ale nawet to nie zawsze jest pewne.

Możliwe rozwiązanie

Myślę, że to może być możliwe rozwiązanie:

SELECT wp_posts.*
FROM   wp_posts
WHERE  id IN (
  SELECT max(id)
  FROM wp_posts
  WHERE (post_author, post_date) = (
    SELECT   post_author, max(post_date)
    FROM     wp_posts
    WHERE    wp_posts.post_status='publish'
             AND wp_posts.post_type='post'
    GROUP BY post_author
  ) AND wp_posts.post_status='publish'
    AND wp_posts.post_type='post'
  GROUP BY post_author
)

Na wewnętrzne zapytanie zwracam maksymalną datę publikacji dla każdego autora. Następnie biorę pod uwagę fakt, że ten sam autor może teoretycznie mieć dwa posty w tym samym czasie, więc otrzymuję tylko maksymalny identyfikator. A potem zwracam wszystkie wiersze, które mają te maksymalne identyfikatory. Można to zrobić szybciej, używając sprzężeń zamiast klauzuli IN.

(Jeśli jesteś pewien, że IDto tylko rośnie, a jeśli ID1 > ID2to oznacza post_date1 > post_date2, to zapytanie może być znacznie prostsze, ale nie jestem pewien, czy tak jest).

fthiella
źródło
To extension to GROUP Byciekawa lektura, dzięki za to.
Rob Forrest
2
Przykład, w którym się nie udaje: sztuczka GROUP BY została zoptymalizowana
ypercubeᵀᴹ
Nieagregowane kolumny w wybranych wyrażeniach z GROUP BY nie działają już domyślnie z MySQL 5.7: stackoverflow.com/questions/34115174/… . Który IMHO jest znacznie bezpieczniejszy i zmusza niektóre osoby do pisania bardziej wydajnych zapytań.
rink.attendant. 6
Czy ta odpowiedź nie używa podzapytania? Czy oryginalny plakat nie pyta o rozwiązanie, które NIE korzysta z podzapytania?
TV-C-15
1
@ TV-C-15 problemem jest uciekanie się z podzapytania, a ja wyjaśniam, dlaczego uciekanie się z podzapytania nie zadziała. Nawet zaakceptowana odpowiedź wykorzystuje podzapytanie, ale zaczyna wyjaśniać, dlaczego uciekanie się jest złym pomysłem ( użycie ORDER BY w podzapytaniu nie jest najlepszym rozwiązaniem tego problemu )
fthiella,
9

To, co zamierzasz przeczytać, jest raczej hakerskie, więc nie próbuj tego w domu!

Ogólnie w SQL odpowiedź na twoje pytanie brzmi NIE , ale ze względu na zrelaksowany tryb GROUP BY(wspomniany przez @bluefeet ) odpowiedź w MySQL brzmi TAK .

Załóżmy, że masz indeks BTREE na (post_status, post_type, post_author, post_date). Jak wygląda indeks pod maską?

(post_status = 'opublikuj', post_type = 'post', post_author = 'użytkownik A', post_date = '2012-12-01') (post_status = 'opublikuj', post_type = 'post', post_author = 'użytkownik A', post_date = '2012-12-31') (post_status = 'opublikuj', post_type = 'post', post_author = 'użytkownik B', post_date = '2012-10-01') (post_status = 'opublikuj', post_type = ' post ”, post_author =„ użytkownik B ”, post_date =„ 2012-12-01 ”)

Oznacza to, że dane są sortowane według wszystkich pól w porządku rosnącym.

Podczas wykonywania GROUP BYdomyślnie sortuje dane według pola grupującego ( post_authorw naszym przypadku; post_status, typ_typu są wymagane przez WHEREklauzulę), a jeśli istnieje zgodny indeks, pobiera dane dla każdego pierwszego rekordu w porządku rosnącym. To jest zapytanie pobierze następujące (pierwszy post dla każdego użytkownika):

(post_status = 'opublikuj', post_type = 'post', post_author = 'użytkownik A', post_date = '2012-12-01') (post_status = 'opublikuj', post_type = 'post', post_author = 'użytkownik B', post_date = „2012-10-01”)

Ale GROUP BYw MySQL pozwala jawnie określić kolejność. A kiedy poprosisz post_userw kolejności malejącej, przejdzie on przez nasz indeks w odwrotnej kolejności, wciąż biorąc pierwszy rekord dla każdej grupy, która jest rzeczywiście ostatnia.

To jest

...
WHERE wp_posts.post_status='publish' AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author DESC

da nam

(post_status = 'opublikuj', post_type = 'post', post_author = 'użytkownik B', post_date = '2012-12-01') (post_status = 'opublikuj', post_type = 'post', post_author = 'użytkownik A', post_date = „2012-12-31”)

Teraz, kiedy zamawiasz wyniki grupowania według post_date, otrzymujesz pożądane dane.

SELECT wp_posts.*
FROM wp_posts
WHERE wp_posts.post_status='publish' AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author DESC
ORDER BY wp_posts.post_date DESC;

NB :

Nie to poleciłbym dla tego konkretnego zapytania. W takim przypadku użyłbym nieco zmodyfikowanej wersji sugerowanej przez @bluefeet . Ale ta technika może być bardzo przydatna. Spójrz na moją odpowiedź tutaj: Pobieranie ostatniego rekordu w każdej grupie

Pułapki : wady tego podejścia

  • wynik zapytania zależy od indeksu, co jest sprzeczne z duchem SQL (indeksy powinny tylko przyspieszać zapytania);
  • indeks nie wie nic o jego wpływie na zapytanie (ty lub ktoś w przyszłości może uznać, że indeks jest zbyt pochłaniający zasoby i jakoś go zmienić, przerywając wyniki zapytania, a nie tylko jego wydajność)
  • jeśli nie rozumiesz, jak działa zapytanie, najprawdopodobniej zapomnisz wyjaśnienia za miesiąc, a zapytanie spowoduje zamieszanie ciebie i twoich kolegów.

Zaletą jest wydajność w trudnych przypadkach. W takim przypadku wydajność zapytania powinna być taka sama, jak w zapytaniu @ bluefeet, ze względu na ilość danych zaangażowanych w sortowanie (wszystkie dane są ładowane do tabeli tymczasowej, a następnie sortowane; przy okazji jego zapytanie również wymaga (post_status, post_type, post_author, post_date)indeksu) .

Co sugerowałbym :

Jak powiedziałem, zapytania te powodują, że MySQL marnuje czas na sortowanie potencjalnie dużych ilości danych w tabeli tymczasowej. W przypadku, gdy potrzebujesz stronicowania (dotyczy to LIMIT), większość danych jest nawet odrzucana. Chciałbym zminimalizować ilość posortowanych danych: to posortować i ograniczyć minimum danych w podzapytaniu, a następnie dołączyć ponownie do całej tabeli.

SELECT * 
FROM wp_posts
INNER JOIN
(
  SELECT max(post_date) post_date, post_author
  FROM wp_posts
  WHERE post_status='publish' AND post_type='post'
  GROUP BY post_author
  ORDER BY post_date DESC
  -- LIMIT GOES HERE
) p2 USING (post_author, post_date)
WHERE post_status='publish' AND post_type='post';

To samo zapytanie przy użyciu podejścia opisanego powyżej:

SELECT *
FROM (
  SELECT post_id
  FROM wp_posts
  WHERE post_status='publish' AND post_type='post'
  GROUP BY post_author DESC
  ORDER BY post_date DESC
  -- LIMIT GOES HERE
) as ids
JOIN wp_posts USING (post_id);

Wszystkie te zapytania wraz z ich planami wykonania na SQLFiddle .

Newtover
źródło
To interesująca technika, którą tam wybrałeś. Dwie rzeczy: mówisz, nie próbuj tego w domu, jakie są potencjalne pułapki? po drugie, wspominasz o nieco zmodyfikowanej wersji odpowiedzi bluefeeta, co by to było?
Rob Forrest,
Dzięki za to, interesujące jest to, że ktoś atakuje problem w inny sposób. Ponieważ mój zestaw danych nie jest w pobliżu twoich wierszy 18M +, nie sądzę, aby wydajność była tak istotna jak łatwość konserwacji, więc myślę, że twoje późniejsze opcje są prawdopodobnie bardziej odpowiednie. Podoba mi się pomysł ograniczenia wewnątrz podzapytania.
Rob Forrest
8

Spróbuj tego. Wystarczy pobrać listę najnowszych dat postów od każdego autora . Otóż ​​to

SELECT wp_posts.* FROM wp_posts WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post' AND wp_posts.post_date IN(SELECT MAX(wp_posts.post_date) FROM wp_posts GROUP BY wp_posts.post_author) 
sanchitkhanna26
źródło
@Rob Forrest, sprawdź moje rozwiązanie. Mam nadzieję, że to rozwiązuje twoje pytanie!
sanchitkhanna26
1
Przepraszam, nie sądzę, żeby to zadziałało. Na przykład, jeśli zarówno autor 1, jak i autor 2 opublikują coś 01/02/13, a następnie autor 2 opublikuje coś nowego 08/02/13, wszystkie 3 posty zostaną zwrócone. Tak, pole daty i godziny zawiera czas, więc sytuacja jest mniej prawdopodobna, ale w żadnym wypadku nie jest gwarantowana na wystarczająco dużym zestawie danych.
Rob Forrest
+1 za korzystanie z post_date IN (select max(...) ...). Jest to bardziej wydajne niż robienie grupy w podselekcji
Seaux
tylko dla wyjaśnienia, jest to bardziej optymalne, jeśli zaindeksowałeś post_author.
Seaux
1
IN ( SELECT ... )jest znacznie mniej wydajny niż równoważny JOIN.
Rick James
3

Nie. Nie ma sensu porządkowanie rekordów przed grupowaniem, ponieważ grupowanie spowoduje mutację zestawu wyników. Preferowana jest metoda zapytania częściowego. Jeśli to idzie zbyt wolno, musiałbyś zmienić projekt tabeli, na przykład przechowując identyfikator ostatniego postu dla każdego autora w osobnej tabeli lub wprowadzić kolumnę logiczną wskazującą dla każdego autora, który z jego postów jest ostatnim jeden.

Dennisch
źródło
Zastanawiasz się, jak zareagowałbyś na komentarze Bluefeet, że ten typ zapytania nie jest poprawną składnią SQL, a zatem nie jest przenośny na różnych platformach baz danych? Istnieją również obawy, że nie ma gwarancji, że za każdym razem przyniosą one prawidłowe wyniki.
Rob Forrest
2

Wystarczy użyć funkcji max i funkcji grupy

    select max(taskhistory.id) as id from taskhistory
            group by taskhistory.taskid
            order by taskhistory.datum desc
Konstantin XFlash Stratigenas
źródło
3
Co zrobić, jeśli ten o najwyższym identyfikatorze nie jest ostatnio opublikowany? Przykładem może być to, że autor trzymał swój post w szkicu przez długi okres czasu, zanim go opublikował.
Rob Forrest,
0

Podsumowując, standardowe rozwiązanie wykorzystuje nieskorelowane podzapytanie i wygląda następująco:

SELECT x.*
  FROM my_table x
  JOIN (SELECT grouping_criteria,MAX(ranking_criterion) max_n FROM my_table GROUP BY grouping_criteria) y
    ON y.grouping_criteria = x.grouping_criteria
   AND y.max_n = x.ranking_criterion;

Jeśli używasz starożytnej wersji MySQL lub dość małego zestawu danych, możesz użyć następującej metody:

SELECT x.*
  FROM my_table x
  LEFT
  JOIN my_table y
    ON y.joining_criteria = x.joining_criteria
   AND y.ranking_criteria < x.ranking_criteria
 WHERE y.some_non_null_column IS NULL;  
Truskawka
źródło
Kiedy mówisz starożytną wersję, na jakiej wersji MySQL to by działało? Niestety nie, zestaw danych w moim przykładzie jest dość duży.
Rob Forrest
Będzie działać (powoli) na dowolnej wersji. Starsze wersje nie mogą używać podkwerend.
Strawberry
Tak, metoda nr 2 (wersja, którą wypróbowałem jest stąd ) nie działa na dużym zestawie danych (miliony wierszy), generuje błąd utraconego połączenia . Metoda nr 1 zajmuje ~ 15 sekund, aby wykonać zapytanie. Początkowo chciałem unikać używania zagnieżdżonych zapytań, ale to sprawiło, że ponownie się zastanowiłem. Dziękuję Ci!
aexl
@TheSexiestManinJamaica Tak. W ciągu 3,5 roku niewiele się zmieniło. Zakładając, że zapytanie samo w sobie jest wydajne, czas jego wykonania zależy w dużej mierze od wielkości zbioru danych, rozmieszczenia indeksów i dostępnego sprzętu.
Strawberry
-1

** Zapytania podrzędne mogą mieć zły wpływ na wydajność, jeśli są używane z dużymi zestawami danych **

Oryginalne zapytanie

SELECT wp_posts.*
FROM   wp_posts
WHERE  wp_posts.post_status = 'publish'
       AND wp_posts.post_type = 'post'
GROUP  BY wp_posts.post_author
ORDER  BY wp_posts.post_date DESC; 

Zmodyfikowane zapytanie

SELECT p.post_status,
       p.post_type,
       Max(p.post_date),
       p.post_author
FROM   wp_posts P
WHERE  p.post_status = "publish"
       AND p.post_type = "post"
GROUP  BY p.post_author
ORDER  BY p.post_date; 

ponieważ używam maxw select clause==> max(p.post_date)możliwe jest uniknięcie zapytań subselekcji i uporządkowanie według maksymalnej kolumny po grupie według.

guykaplan
źródło
1
To rzeczywiście zwraca ostatnią datę postu na autora, ale nie ma gwarancji, że reszta zwracanych danych dotyczy postu z najnowszą datą postu.
Rob Forrest,
@RobForrest -> Nie rozumiem dlaczego? dobrze jest rozwinąć swoją odpowiedź i po prostu wyrzucić roszczenia. O ile rozumiem, dane są powiązane, ponieważ używam klauzuli gdzie do filtrowania powiązanych danych.
guykaplan,
1
W pewnym stopniu masz całkowitą rację, każde z 4 wybranych pól będzie odnosić się do maksymalnej liczby post_date, ale to nie odpowiada na zadane pytanie. Na przykład, jeśli dodano post_id lub treść postu, wówczas nie można zagwarantować, że kolumny te pochodzą z tego samego rekordu, co data maksymalna. Aby uzyskać powyższe zapytanie i zwrócić resztę szczegółów postu, musisz uruchomić drugie zapytanie. Jeśli pytanie dotyczyło znalezienia daty ostatniego postu, to tak, odpowiedź byłaby w porządku.
Rob Forrest,
@ guykaplan, podzapytania nie są wolne. Rozmiar zestawu danych nie ma znaczenia. To zależy od tego, jak z niego korzystasz. Zobacz percona.com/blog/2010/03/18/when-the-subselect-runs-faster
Pacerier
@Pacerier: artykuł rzeczywiście pokazuje, w jaki sposób można uzyskać poprawę wydajności dzięki zapytaniom podrzędnym, ale chciałbym zobaczyć, jak przekonwertowałeś dany scenariusz, aby uzyskać lepszą wydajność. a rozmiar danych jest ważny, ponownie w opublikowanym artykule zakładasz, że istnieje tylko jedna tabela do pracy. rozmiar danych nie jest wielkością wiersza, jest wielkością złożoności. Powiedziawszy to, jeśli pracujesz z naprawdę dużą tabelą (nie ma wielu tabel), zapytanie podrzędne może działać znacznie lepiej.
guykaplan
-4

Po pierwsze, nie używaj * w select, wpływa to na ich wydajność i utrudnia korzystanie z grupy według i sortowanie według. Spróbuj tego zapytania:

SELECT wp_posts.post_author, wp_posts.post_date as pdate FROM wp_posts
WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author           
ORDER BY pdate DESC

Jeśli nie określisz tabeli w ORDER BY, tylko alias, uporządkują wynik zaznaczenia.

Bruno Nardini
źródło
Zignoruj ​​zaznaczone *, w tym przykładzie są one zwięzłe. Twoja odpowiedź jest dokładnie taka sama jak w pierwszym przykładzie, który podałem.
Rob Forrest
Alias ​​nie ma wpływu na to, który wiersz zostanie zwrócony, ani na sortowanie wyników.
Rob Forrest