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
( name
w ogrodzie, flower
któ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 BY
do 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_date
jest niezagregowaną kolumną, a jej wartość zostanie oficjalnie nieokreślona, ale prawdopodobnie będzie to pierwsza post_date
napotkana. Ale ponieważ sztuczka GROUP BY jest stosowana do nieuporządkowanej tabeli, nie jest pewne, która jest pierwsza post_date
napotkana.
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 ID
to tylko rośnie, a jeśli ID1 > ID2
to oznacza post_date1 > post_date2
, to zapytanie może być znacznie prostsze, ale nie jestem pewien, czy tak jest).
post_author
ipost_date
nie wystarczą, aby uzyskać unikalny wiersz, więc musi być więcej, aby uzyskać unikalny wiersz napost_author