PILIH BATAS 1 per nilai kolom?

10

Katakanlah saya memiliki tabel berikut

-----------------------------
| user_id   | comment       |
-----------------------------
| 2         | thats cool    |
| 2         | awesome       |
| 3         | i hate this   |
| 3         | okay          |
| 6         | this is weird |
| 6         | hello?        |
| 6         | what is it    |
| 9         | how are you   |
| 16        | too slow      |
| 16        | yes           |
| 17        | alrighty      |
-----------------------------

Bagaimana Anda bisa memilih satu baris per user_id? Jadi hasil saya adalah:

-----------------------------
| user_id   | comment       |
-----------------------------
| 2         | thats cool    |
| 3         | i hate this   |
| 6         | this is weird |
| 9         | how are you   |
| 16        | too slow      |
| 17        | alrighty      |
-----------------------------

Apakah ini mungkin dengan satu permintaan efisien? Atau apakah sub-terpilih itu perlu? Apakah mungkin untuk digunakan DISTINCTpada satu kolom?

Jake Wilson
sumber

Jawaban:

9

Untuk itulah GROUP BYdigunakan. Dapatkan satu baris (per grup). Dalam hal ini, ia akan menampilkan semua yang berbeda user_idnilai dan untuk sisa kolom, Anda dapat (harus) menggunakan fungsi agregat seperti MIN(), MAX(), AVG(), SUM()karena Anda akan memiliki lebih dari satu nilai per kelompok dan hanya satu dapat ditampilkan.

SELECT
    user_id
  , MIN(comment) AS comment  -- it will show the first in alphabetical order  
                             -- you could also use MAX()
FROM
    tableX
GROUP BY
    user_id ;

MySQL juga memungkinkan solusi ortodoks berikut, yang akan mengembalikan satu (lebih atau kurang acak) komentar per pengguna:

SELECT
    user_id
  , comment
FROM
    tableX
GROUP BY
    user_id ;

Kueri terakhir ini tidak akan berfungsi tetapi menimbulkan kesalahan jika ONLY_FULL_GROUP_BYmode (lebih ketat) diaktifkan. Dalam versi 5.7 yang baru dirilis, mode ini adalah default dan fungsi baru ANY_VALUE(),, disediakan. Untuk detail lebih lanjut, lihat Penanganan MySQLGROUP BY halaman. Kueri dapat ditulis sekarang:

SELECT
    user_id
  , ANY_VALUE(comment) AS comment
FROM
    tableX
GROUP BY
    user_id ;

Perhatikan bahwa baik dengan versi "tidak lazim" atau menggunakan ANY_VALUE()fungsi terbaru , jika kita menambahkan lebih banyak kolom dalam SELECTdaftar, nilainya tidak dijamin berasal dari baris yang sama, hanya dari baris di grup yang sama. Cara mereka dipilih tidak benar-benar acak, tergantung pada rencana eksekusi dan indeks yang digunakan.

ypercubeᵀᴹ
sumber
Apakah ada cara lain untuk menentukan baris mana yang akan ditarik untuk user_id? Adakah cara untuk menentukan jenis ORDER BY?
Jake Wilson
Selain MINdan MAX?
ypercubeᵀᴹ
1
Maka itu lebih kompleks. Lihat pertanyaan lain ini: MySQL Query - Bagaimana cara mendapatkan demografi terbaru?
ypercubeᵀᴹ
2
Anda juga akan menemukan banyak masalah serupa di situs SO, di bawah [greatest-n-per-group]tag.
ypercubeᵀᴹ
1
@ T.BrianJones maksud Anda dalam permintaan "tidak lazim", jika Anda menambahkan semua kolom lain dalam daftar SELECT? Ini yang pertama, mereka mungkin bukan dari baris yang sama. Ini tidak benar-benar acak tetapi nilainya bisa dari baris yang berbeda (dari grup yang sama).
ypercubeᵀᴹ