Pesanan MySQL oleh sebelum dikelompokkan oleh

243

Ada banyak pertanyaan serupa yang dapat ditemukan di sini tapi saya tidak berpikir ada yang menjawab pertanyaan dengan memadai.

Saya akan melanjutkan dari pertanyaan paling populer saat ini dan menggunakan contoh mereka jika tidak apa-apa.

Tugas dalam hal ini adalah untuk mendapatkan posting terbaru untuk setiap penulis dalam database.

Contoh query menghasilkan hasil yang tidak dapat digunakan karena tidak selalu posting terbaru yang dikembalikan.

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

Jawaban yang diterima saat ini adalah

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

Sayangnya jawaban ini jelas dan salah sederhana dan dalam banyak kasus menghasilkan hasil yang kurang stabil daripada permintaan asli.

Solusi terbaik saya adalah menggunakan subquery formulir

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 

Pertanyaan saya adalah pertanyaan sederhana: Apakah ada yang memesan baris sebelum pengelompokan tanpa menggunakan subquery?

Sunting : Pertanyaan ini merupakan kelanjutan dari pertanyaan lain dan kekhasan situasi saya sedikit berbeda. Anda dapat (dan harus) berasumsi bahwa ada juga wp_posts.id yang merupakan pengidentifikasi unik untuk pos tertentu itu.

Rob Forrest
sumber
2
Seperti yang Anda sebutkan di komentar untuk jawaban yang diberikan, dimungkinkan untuk memiliki beberapa posting dengan Stempel Waktu yang sama. Jika demikian, tolong berikan contoh dengan data dan hasil yang diharapkan. Dan tolong jelaskan, mengapa Anda mengharapkan hasil ini. post_authordan post_datetidak cukup untuk mendapatkan baris unik, jadi harus ada lebih banyak untuk mendapatkan baris unik perpost_author
Sir Rufo
@ SirRufo Anda benar, saya telah menambahkan hasil edit untuk Anda.
Rob Forrest
There are plenty of similar questions to be found on here but I don't think that any answer the question adequately.Itulah gunanya hadiah.
Lightness Races dalam Orbit
@LightnessRacesinOrbit, jika pertanyaan saat ini sudah memiliki jawaban yang diterima yang menurut saya salah, apa yang akan Anda lakukan?
Rob Forrest
1
Bertanya-tanya mengapa Anda menerima jawaban yang menggunakan subquery - ketika pertanyaan Anda jelas bertanya ... "" Apakah ada pula untuk memesan baris sebelum pengelompokan tanpa menggunakan subquery? "???
TV-C-15

Jawaban:

373

Menggunakan suatu ORDER BYdalam subquery bukanlah solusi terbaik untuk masalah ini.

Solusi terbaik untuk mendapatkan max(post_date)oleh penulis adalah dengan menggunakan subquery untuk mengembalikan tanggal max dan kemudian bergabung dengan itu ke meja Anda pada post_authortanggal max dan.

Solusinya harus:

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

Jika Anda memiliki data sampel berikut:

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')
;

Subquery akan mengembalikan tanggal maksimum dan pembuat:

MaxPostDate | Author
2/1/2013    | Jim

Kemudian karena Anda bergabung kembali ke tabel, pada kedua nilai Anda akan mengembalikan detail lengkap dari posting itu.

Lihat SQL Fiddle dengan Demo .

Untuk memperluas komentar saya tentang menggunakan subquery untuk mengembalikan data ini dengan akurat.

MySQL tidak memaksa Anda untuk GROUP BYsetiap kolom yang Anda sertakan dalam SELECTdaftar. Akibatnya, jika Anda hanya GROUP BYsatu kolom tetapi mengembalikan total 10 kolom, tidak ada jaminan bahwa nilai kolom lain milik milik post_authoryang dikembalikan. Jika kolom tidak ada dalam GROUP BYMySQL, pilih nilai apa yang harus dikembalikan.

Menggunakan subquery dengan fungsi agregat akan menjamin bahwa penulis dan posting yang benar dikembalikan setiap waktu.

Sebagai catatan, sementara MySQL memungkinkan Anda untuk menggunakan ORDER BYdalam subquery dan memungkinkan Anda untuk menerapkan GROUP BYtidak setiap kolom dalam SELECTdaftar perilaku ini tidak diperbolehkan di database lain termasuk SQL Server.

Taryn
sumber
4
Saya melihat apa yang telah Anda lakukan di sana tetapi itu hanya mengembalikan tanggal posting terbaru dibuat, bukan seluruh baris untuk posting terbaru itu.
Rob Forrest
1
@RobForrest, itulah yang dilakukan oleh join. Anda mengembalikan tanggal posting terbaru di subquery oleh penulis dan kemudian bergabung kembali ke Anda wp_postsdi kedua kolom untuk mendapatkan baris penuh.
Taryn
7
@RobForrest Untuk satu, ketika Anda menerapkan GROUP BYhanya satu kolom, tidak ada jaminan bahwa nilai-nilai di kolom lain akan secara konsisten benar. Sayangnya, MySQL memungkinkan jenis SELECT / GROUPing ini terjadi, sedangkan produk lain tidak. Dua, sintaks menggunakan ORDER BYsubquery saat diizinkan di MySQL tidak diperbolehkan dalam produk database lain termasuk SQL Server. Anda harus menggunakan solusi yang akan mengembalikan hasil yang tepat setiap kali dieksekusi.
Taryn
2
Untuk penskalaan, senyawa INDEX(post_author, post_date)ini penting.
Rick James
1
@ jtcotton63 Benar, tetapi jika Anda memasukkan post_idpertanyaan dalam Anda, maka secara teknis Anda harus mengelompokkannya juga, yang kemungkinan besar akan memengaruhi hasil Anda.
Taryn
20

Solusi Anda menggunakan ekstensi untuk klausa GROUP BY yang memungkinkan untuk dikelompokkan berdasarkan beberapa bidang (dalam hal ini, adil post_author):

GROUP BY wp_posts.post_author

dan pilih kolom yang tidak teragregasi:

SELECT wp_posts.*

yang tidak tercantum dalam grup dengan klausa, atau yang tidak digunakan dalam fungsi agregat (MIN, MAX, COUNT, dll.).

Penggunaan ekstensi yang benar untuk klausa GROUP BY

Ini berguna ketika semua nilai kolom non-agregat sama untuk setiap baris.

Sebagai contoh, misalkan Anda memiliki meja GardensFlowers( nametaman, floweryang tumbuh di taman):

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

dan Anda ingin mengekstrak semua bunga yang tumbuh di taman, di mana banyak bunga tumbuh. Maka Anda harus menggunakan subquery, misalnya Anda bisa menggunakan ini:

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

Jika Anda perlu mengekstrak semua bunga yang merupakan satu-satunya bunga di garder, Anda dapat mengubah kondisi HAVING HAVING COUNT(DISTINCT flower)=1, tetapi MySql juga memungkinkan Anda untuk menggunakan ini:

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

tidak ada subquery, bukan SQL standar, tetapi lebih sederhana.

Penggunaan ekstensi yang salah untuk klausa GROUP BY

Tetapi apa yang terjadi jika Anda PILIH kolom non-agregat yang tidak sama untuk setiap baris? Nilai apa yang dipilih MySql untuk kolom itu?

Sepertinya MySql selalu memilih nilai PERTAMA yang dijumpainya.

Untuk memastikan bahwa nilai pertama yang dihadapinya persis dengan nilai yang Anda inginkan, Anda perlu menerapkan GROUP BYkueri yang dipesan, maka kebutuhan untuk menggunakan subquery. Anda tidak bisa melakukannya sebaliknya.

Dengan asumsi bahwa MySql selalu memilih baris pertama yang dihadapinya, Anda dengan benar menyortir baris sebelum GROUP BY. Namun sayangnya, jika Anda membaca dokumentasi dengan cermat, Anda akan melihat bahwa asumsi ini tidak benar.

Saat memilih kolom non-agregat yang tidak selalu sama, MySql bebas memilih nilai apa pun, sehingga nilai yang dihasilkannya benar-benar tidak dapat ditentukan .

Saya melihat bahwa trik ini untuk mendapatkan nilai pertama dari kolom non-agregat banyak digunakan, dan biasanya / hampir selalu berhasil, saya kadang-kadang menggunakannya juga (dengan risiko saya sendiri). Tetapi karena itu tidak didokumentasikan, Anda tidak dapat mengandalkan perilaku ini.

Tautan ini (terima kasih ypercube!) Trik GROUP BY telah dioptimalkan menunjukkan situasi di mana permintaan yang sama mengembalikan hasil yang berbeda antara MySql dan MariaDB, mungkin karena mesin pengoptimalan yang berbeda.

Jadi, jika trik ini berhasil, itu hanya masalah keberuntungan.

The jawaban yang diterima pada pertanyaan lain terlihat salah kepada saya:

HAVING wp_posts.post_date = MAX(wp_posts.post_date)

wp_posts.post_dateadalah kolom non-agregat, dan nilainya akan secara resmi tidak ditentukan, tetapi kemungkinan akan menjadi yang pertama post_dateditemui. Tetapi karena trik GROUP BY diterapkan pada tabel yang tidak berurutan, tidak yakin yang mana yang pertama kali post_dateditemukan.

Mungkin akan mengembalikan posting yang merupakan satu-satunya posting dari penulis tunggal, tetapi bahkan ini tidak selalu pasti.

Solusi yang memungkinkan

Saya pikir ini bisa menjadi solusi yang mungkin:

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
)

Pada permintaan dalam, saya mengembalikan tanggal posting maksimum untuk setiap penulis. Saya kemudian mempertimbangkan fakta bahwa penulis yang sama secara teori dapat memiliki dua posting pada saat yang sama, jadi saya hanya mendapatkan ID maksimum. Dan kemudian saya mengembalikan semua baris yang memiliki ID maksimum itu. Itu bisa dibuat lebih cepat menggunakan gabungan bukannya klausa IN.

(Jika Anda yakin itu IDhanya meningkat, dan jika ID1 > ID2juga berarti demikian post_date1 > post_date2, maka kueri dapat dibuat lebih sederhana, tapi saya tidak yakin apakah ini masalahnya).

fthiella
sumber
Itu extension to GROUP Bybacaan yang menarik, terima kasih untuk itu.
Rob Forrest
2
Sebuah contoh di mana ia gagal: Trik GROUP BY telah dioptimalkan jauh
ypercubeᵀᴹ
Kolom yang tidak teragregasi dalam ekspresi tertentu dengan GROUP BY tidak lagi berfungsi secara default dengan MySQL 5.7: stackoverflow.com/questions/34115174/… . IMHO mana yang jauh lebih aman dan memaksa beberapa orang untuk menulis pertanyaan yang lebih efisien.
rink.attendant.6
Tidakkah jawaban ini menggunakan subquery? Bukankah Poster Asli meminta solusi yang TIDAK menggunakan subquery?
TV-C-15
1
@ TV-C-15 masalahnya adalah dengan menggunakan subquery, dan saya menjelaskan mengapa menggunakan subquery tidak akan berhasil. Bahkan jawaban yang diterima menggunakan subquery tetapi mulai menjelaskan mengapa resorting adalah ide yang buruk ( Menggunakan ORDER OLEH dalam subquery bukanlah solusi terbaik untuk masalah ini )
fthiella
9

Apa yang akan Anda baca agak basi, jadi jangan coba ini di rumah!

Dalam SQL secara umum jawaban untuk pertanyaan Anda adalah TIDAK , tetapi karena mode santai dari GROUP BY(disebutkan oleh @bluefeet ), jawabannya adalah YA di MySQL.

Misalkan, Anda memiliki indeks BTREE pada (post_status, post_type, post_author, post_date). Bagaimana indeks terlihat seperti di bawah tenda?

(post_status = 'publikasikan', post_type = 'posting', post_author = 'pengguna A', post_date = '2012-12-01') (post_status = 'publikasikan', post_type = 'posting', post_author = 'pengguna A', post_date = '2012-12-31') (post_status = 'publish', post_type = 'post', post_author = 'pengguna B', post_date = '2012-10-01') (post_status = 'publish', post_type = ' posting ', post_author =' pengguna B ', post_date =' 2012-12-01 ')

Itu adalah data yang diurutkan berdasarkan semua bidang itu dalam urutan menaik.

Ketika Anda melakukan secara GROUP BYdefault itu mengurutkan data oleh bidang pengelompokan ( post_author, dalam kasus kami; post_status, post_type diperlukan oleh WHEREklausa) dan jika ada indeks yang cocok, dibutuhkan data untuk setiap catatan pertama dalam urutan menaik. Itu adalah permintaan yang akan mengambil yang berikut (posting pertama untuk setiap pengguna):

(post_status = 'publikasikan', post_type = 'posting', post_author = 'pengguna A', post_date = '2012-12-01') (post_status = 'publikasikan', post_type = 'posting', post_author = 'pengguna B', post_date = '2012-10-01')

Tetapi GROUP BYdi MySQL, Anda dapat menentukan urutan secara eksplisit. Dan ketika Anda meminta post_userdalam urutan menurun, itu akan berjalan melalui indeks kami dalam urutan yang berlawanan, masih mengambil catatan pertama untuk setiap kelompok yang sebenarnya terakhir.

Itu adalah

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

akan memberi kita

(post_status = 'publikasikan', post_type = 'posting', post_author = 'pengguna B', post_date = '2012-12-01') (post_status = 'publikasikan', post_type = 'posting', post_author = 'pengguna A', post_date = '2012-12-31')

Sekarang, ketika Anda memesan hasil pengelompokan dengan post_date, Anda mendapatkan data yang Anda inginkan.

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 :

Ini bukan yang saya sarankan untuk permintaan khusus ini. Dalam hal ini, saya akan menggunakan versi yang sedikit dimodifikasi dari apa yang disarankan @bluefeet . Namun teknik ini mungkin sangat berguna. Lihatlah jawaban saya di sini: Mengambil catatan terakhir di setiap kelompok

Perangkap : Kelemahan dari pendekatan ini adalah itu

  • hasil permintaan tergantung pada indeks, yang bertentangan dengan semangat SQL (indeks seharusnya hanya mempercepat permintaan);
  • indeks tidak tahu apa-apa tentang pengaruhnya terhadap kueri (Anda atau orang lain di masa depan mungkin menganggap indeks terlalu memakan sumber daya dan mengubahnya entah bagaimana, menghancurkan hasil kueri, tidak hanya kinerjanya)
  • jika Anda tidak memahami cara kerja kueri, kemungkinan besar Anda akan melupakan penjelasan dalam sebulan dan kueri akan membingungkan Anda dan kolega Anda.

Keuntungannya adalah kinerja dalam hard case. Dalam hal ini, kinerja kueri harus sama dengan dalam permintaan @ bluefeet, karena jumlah data yang terlibat dalam penyortiran (semua data dimuat ke tabel sementara dan kemudian disortir; btw, kuerinya memerlukan (post_status, post_type, post_author, post_date)indeks juga) .

Apa yang saya sarankan :

Seperti yang saya katakan, pertanyaan-pertanyaan itu membuat MySQL membuang waktu berpotensi data dalam jumlah besar dalam tabel sementara. Jika Anda perlu paging (yaitu LIMIT terlibat) sebagian besar data bahkan dibuang. Apa yang akan saya lakukan adalah meminimalkan jumlah data yang diurutkan: yaitu mengurutkan dan membatasi data minimum dalam subquery dan kemudian bergabung kembali ke seluruh tabel.

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';

Permintaan yang sama menggunakan pendekatan yang dijelaskan di atas:

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);

Semua pertanyaan itu dengan rencana eksekusi mereka pada SQLFiddle .

baru ditemukan
sumber
Itu teknik menarik yang Anda miliki di sana. Dua hal: Anda mengatakan jangan mencobanya di rumah, apa saja jebakan yang potensial? kedua, Anda menyebutkan versi jawaban bluefeet yang sedikit dimodifikasi, apakah itu?
Rob Forrest
Terima kasih untuk itu, menarik melihat seseorang yang menyerang masalah dengan cara yang berbeda. Karena kumpulan data saya tidak berada di dekat baris 18M + Anda, saya tidak berpikir kinerja sama pentingnya dengan pemeliharaan, jadi saya pikir pilihan Anda nanti mungkin lebih cocok. Saya suka gagasan batas di bagian dalam subquery.
Rob Forrest
8

Coba yang ini. Hanya dapatkan daftar tanggal posting terbaru dari masing-masing penulis . Itu dia

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
sumber
@Rob Forrest, periksa solusi saya. Mudah-mudahan itu menyelesaikan pertanyaan Anda!
sanchitkhanna26
1
Maaf, saya tidak berpikir itu akan berhasil. Sebagai contoh jika kedua penulis 1 dan penulis 2 menerbitkan sesuatu pada 01/02/13 dan kemudian penulis 2 memposting sesuatu yang baru pada 08/02/13, ketiga posting akan dikembalikan. Ya bidang datetime termasuk waktu sehingga situasinya lebih kecil tetapi tidak berarti apakah itu dijamin pada dataset yang cukup besar.
Rob Forrest
+1 untuk menggunakan post_date IN (select max(...) ...). Ini lebih efisien daripada melakukan grup dalam sub pilih, lihat dev.mysql.com/doc/refman/5.6/en/subquery-optimization.html
Seaux
hanya untuk memperjelas, itu hanya lebih optimal jika Anda memiliki post_author diindeks.
Seaux
1
IN ( SELECT ... )jauh lebih efisien daripada GABUNGAN setara.
Rick James
3

Tidak. Tidak masuk akal untuk memesan catatan sebelum pengelompokan, karena pengelompokan akan mengubah set hasil. Cara subquery adalah cara yang disukai. Jika ini berjalan terlalu lambat Anda harus mengubah desain tabel Anda, misalnya dengan menyimpan id dari posting terakhir untuk setiap penulis dalam tabel terpisah, atau memperkenalkan kolom boolean yang menunjukkan untuk setiap penulis yang posnya adalah yang terakhir satu.

Dennisch
sumber
Dennish, bagaimana Anda menanggapi komentar Bluefeet bahwa jenis pertanyaan ini tidak sintaks SQL yang benar dan karena itu tidak portabel di seluruh platform database? Ada juga kekhawatiran bahwa tidak ada jaminan bahwa ini akan menghasilkan hasil yang benar setiap waktu.
Rob Forrest
2

Cukup gunakan fungsi maks dan fungsi grup

    select max(taskhistory.id) as id from taskhistory
            group by taskhistory.taskid
            order by taskhistory.datum desc
Konstantin XFlash Stratigenas
sumber
3
Bagaimana jika yang memiliki id tertinggi bukan yang terakhir diposting? Contohnya adalah penulis memegang postingannya dalam konsep untuk waktu yang lama sebelum mempostingnya.
Rob Forrest
0

Sekadar rekap, solusi standar menggunakan subquery yang tidak berkorelasi dan terlihat seperti ini:

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;

Jika Anda menggunakan versi kuno MySQL, atau kumpulan data yang cukup kecil, maka Anda dapat menggunakan metode berikut:

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;  
Stroberi
sumber
Ketika Anda mengatakan versi kuno, versi MySQL apa yang akan dijalankan? Dan maaf tidak, dataset cukup besar dalam contoh saya.
Rob Forrest
Ini akan bekerja (lambat) pada versi apa pun. Versi yang lebih lama tidak dapat menggunakan subqueries.
Strawberry
Yap, metode # 2 (versi yang saya coba dari sini ) tidak akan berfungsi pada dataset besar (jutaan baris), melempar kesalahan koneksi yang hilang . Metode # 1 membutuhkan ~ 15 detik untuk menjalankan kueri. Saya awalnya ingin menghindari menggunakan kueri bersarang, tetapi ini membuat saya mempertimbangkan kembali. Terima kasih!
aexl
@TheSexiestManinJamaica Ya. Tidak banyak yang berubah dalam 3,5 tahun. Dengan asumsi permintaan itu sendiri efisien, maka waktu yang diperlukan untuk mengeksekusi sangat tergantung pada ukuran dataset, pengaturan indeks, dan perangkat keras yang tersedia.
Strawberry
-1

** Sub kueri mungkin berdampak buruk pada kinerja bila digunakan dengan kumpulan data besar **

Permintaan asli

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; 

Kueri yang dimodifikasi

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; 

karena saya menggunakan maxdi select clause==> max(p.post_date)adalah mungkin untuk menghindari permintaan pilih sub dan memesan dengan kolom max setelah grup oleh.

guykaplan
sumber
1
Ini memang mengembalikan post_date terbaru per penulis tetapi tidak ada jaminan bahwa sisa data yang dikembalikan berkaitan dengan posting dengan post_date terbaru.
Rob Forrest
@RobForrest -> Saya tidak mengerti mengapa? itu ide yang bagus untuk menguraikan jawaban Anda dan hanya membuang klaim. Sejauh yang saya mengerti data dijamin terkait seperti yang saya gunakan di mana klausa untuk menyaring data terkait.
guykaplan
1
Pada tingkat tertentu, Anda sepenuhnya benar, masing-masing dari 4 bidang yang Anda pilih akan berhubungan dengan post_date maksimum, tetapi ini tidak menjawab pertanyaan yang ditanyakan. Misalnya, jika Anda menambahkan post_id, atau konten posting, maka kolom-kolom itu tidak akan dijamin berasal dari catatan yang sama dengan tanggal maksimum. Untuk mendapatkan kueri Anda di atas untuk mengembalikan sisa detail posting Anda harus menjalankan kueri kedua. Jika pertanyaannya adalah tentang menemukan tanggal posting terbaru, maka ya jawaban Anda akan baik-baik saja.
Rob Forrest
@ guykaplan, Subqueries tidak lambat. Ukuran kumpulan data tidak masalah. Itu tergantung pada bagaimana Anda menggunakannya. Lihat percona.com/blog/2010/03/18/when-the-subselect-runs-faster
Pacerier
@ Peracerier: artikel itu memang menunjukkan bagaimana Anda bisa mendapatkan manfaat kinerja dari sub-kueri, tapi saya akan senang melihat Anda mengonversi skenario yang diberikan untuk berkinerja lebih baik. dan Ukuran data itu penting, sekali lagi dalam artikel yang Anda posting Anda mengasumsikan hanya ada satu tabel untuk bekerja. ukuran data tidak berdasarkan ukuran baris, adalah ukuran kompleksitas. karena itu, jika Anda bekerja dengan tabel yang benar-benar besar (tidak banyak tabel yang terlibat), sub-kueri dapat bekerja lebih baik.
guykaplan
-4

Pertama, jangan gunakan * dalam pilih, memengaruhi kinerja mereka dan menghalangi penggunaan grup berdasarkan dan dipesan oleh. Coba kueri ini:

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

Ketika Anda tidak menentukan tabel dalam ORDER BY, hanya alias, mereka akan memesan hasil pilih.

Bruno Nardini
sumber
Abaikan pilih *, itu untuk singkatnya dalam contoh ini. Jawaban Anda persis sama dengan contoh pertama yang saya berikan.
Rob Forrest
Alias ​​tidak memengaruhi baris mana yang dikembalikan atau memilah hasil.
Rob Forrest