La tua soluzione utilizza un'estensione della clausola GROUP BY che consente di raggruppare per alcuni campi (in questo caso, solo post_author
):
GROUP BY wp_posts.post_author
e seleziona colonne non aggregate:
SELECT wp_posts.*
che non sono elencati nella clausola group by o che non sono utilizzati in una funzione aggregata (MIN, MAX, COUNT, ecc.).
Uso corretto dell'estensione alla clausola GROUP BY
Ciò è utile quando tutti i valori delle colonne non aggregate sono uguali per ogni riga.
Ad esempio, supponiamo di avere un tavolo GardensFlowers
( name
del giardino, flower
che cresce nel giardino):
INSERT INTO GardensFlowers VALUES
('Central Park', 'Magnolia'),
('Hyde Park', 'Tulip'),
('Gardens By The Bay', 'Peony'),
('Gardens By The Bay', 'Cherry Blossom');
e vuoi estrarre tutti i fiori che crescono in un giardino, dove crescono più fiori. Quindi devi usare una sottoquery, ad esempio puoi usare questo:
SELECT GardensFlowers.*
FROM GardensFlowers
WHERE name IN (SELECT name
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)>1);
Se invece devi estrarre tutti i fiori che sono gli unici fiori del giardiniere, puoi semplicemente cambiare la condizione HAVING in HAVING COUNT(DISTINCT flower)=1
, ma MySql ti consente anche di usare questo:
SELECT GardensFlowers.*
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)=1;
nessuna subquery, non standard SQL, ma più semplice.
Uso errato dell'estensione alla clausola GROUP BY
Ma cosa succede se selezioni colonne non aggregate che non sono uguali per ogni riga? Qual è il valore che MySql sceglie per quella colonna?
Sembra che MySql scelga sempre il PRIMO valore che incontra.
Per assicurarsi che il primo valore che incontra sia esattamente il valore desiderato, è necessario applicare GROUP BY
a una query ordinata, quindi la necessità di utilizzare una sottoquery. Non puoi farlo diversamente.
Dato che MySql sceglie sempre la prima riga che incontra, stai ordinando correttamente le righe prima di GROUP BY. Ma sfortunatamente, se leggi attentamente la documentazione, noterai che questa ipotesi non è vera.
Quando si selezionano colonne non aggregate che non sono sempre le stesse, MySql è libero di scegliere qualsiasi valore, quindi il valore risultante che mostra effettivamente è indeterminato .
Vedo che questo trucco per ottenere il primo valore di una colonna non aggregata viene usato molto e di solito / quasi sempre funziona, lo uso anche a volte (a mio rischio). Ma poiché non è documentato, non puoi fare affidamento su questo comportamento.
Questo link (grazie a ypercube!) Il trucco GROUP BY è stato ottimizzato per mostrare una situazione in cui la stessa query restituisce risultati diversi tra MySql e MariaDB, probabilmente a causa di un motore di ottimizzazione diverso.
Quindi, se questo trucco funziona, è solo una questione di fortuna.
La risposta accettata sull'altra domanda mi sembra sbagliata:
HAVING wp_posts.post_date = MAX(wp_posts.post_date)
wp_posts.post_date
è una colonna non aggregata e il suo valore sarà ufficialmente indeterminato, ma sarà probabilmente il primo post_date
rilevato. Ma poiché il trucco GROUP BY viene applicato a una tabella non ordinata, non è sicuro quale sia il primo che si post_date
incontra.
Probabilmente restituirà post che sono gli unici post di un singolo autore, ma anche questo non è sempre certo.
Una possibile soluzione
Penso che questa potrebbe essere una possibile soluzione:
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
)
Nella query interna sto restituendo la data massima di pubblicazione per ogni autore. Sto quindi prendendo in considerazione il fatto che lo stesso autore potrebbe teoricamente avere due post contemporaneamente, quindi ottengo solo l'ID massimo. E poi sto restituendo tutte le righe che hanno quegli ID massimi. Potrebbe essere reso più veloce usando i join anziché la clausola IN.
(Se sei sicuro che ID
sta solo aumentando, e se ID1 > ID2
significa anche quello post_date1 > post_date2
, allora la query potrebbe essere resa molto più semplice, ma non sono sicuro che sia così).
post_author
epost_date
non sono sufficienti per ottenere una riga univoca, quindi ci deve essere altro per ottenere una riga unica perpost_author