Mengapa wildcard dalam pernyataan GROUP BY tidak berfungsi?

29

Saya mencoba membuat pernyataan SQL berikut berfungsi, tetapi saya mendapatkan kesalahan sintaksis:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.*

Di sini, A adalah tabel lebar dengan 40 kolom dan saya ingin menghindari daftar setiap nama kolom dalam klausa GROUP BY jika memungkinkan. Saya punya banyak tabel seperti itu di mana saya harus menjalankan kueri yang sama, jadi saya harus menulis Prosedur Tersimpan. Apa cara terbaik untuk mendekati ini?

Saya menggunakan MS SQL Server 2008.

Maximus Anonim
sumber

Jawaban:

32

GROUP BY A.* tidak diizinkan dalam SQL.

Anda bisa melewati ini dengan menggunakan subquery tempat Anda mengelompokkannya, dan kemudian bergabung:

SELECT A.*, COALESCE(B.cnt, 0) AS Count_B_Foo
FROM TABLE1 AS A
  LEFT JOIN 
      ( SELECT FKey, COUNT(foo) AS cnt
        FROM TABLE2 
        GROUP BY FKey
      ) AS B 
    ON A.PKey = B.FKey ;

Ada fitur dalam standar SQL-2003 untuk memungkinkan dalam SELECTdaftar, kolom yang tidak ada dalam GROUP BYdaftar, selama mereka secara fungsional bergantung padanya. Jika fitur itu telah diimplementasikan dalam SQL-Server, permintaan Anda bisa ditulis sebagai:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.pk                          --- the Primary Key of table A

Sayangnya, fitur ini belum diimplementasikan, bahkan dalam versi SQL-Server 2012 - dan tidak dalam DBMS lain sejauh yang saya tahu. Kecuali untuk MySQL yang memilikinya tetapi tidak memadai (tidak memadai seperti: kueri di atas akan berfungsi tetapi mesin tidak akan melakukan pengecekan untuk dependensi fungsional dan kueri tertulis lainnya akan menunjukkan kesalahan, hasil semi-acak).

Ketika @Mark Byers memberi tahu kami dalam komentar, PostgreSQL 9.1 menambahkan fitur baru yang dirancang untuk tujuan ini. Ini lebih membatasi daripada implementasi MySQL.

ypercubeᵀᴹ
sumber
Bisakah Anda menyebutkan beberapa RDBMS yang mengimplementasikan porsi standar itu seperti yang tertulis? Saya tahu, misalnya, bahwa MySQL akan memungkinkan Anda (mengingat pengaturan yang tepat) untuk memasukkan item yang tidak termasuk dalam GROUP BYklausa dalam SELECTdaftar, tetapi membiarkannya tidak terdefinisi untuk baris mana nilai tersebut akan berasal (jadi jika kolom atau ekspresi tidak tidak secara fungsional bergantung pada ekspresi pengelompokan, maka itu bisa berasal dari baris apa pun dalam grup).
Adam Robinson
@ Adam: Tidak, saya tahu tidak ada RDBMS yang mengimplementasikannya. MySQL memilikinya tetapi tidak memadai, seperti komentar Anda katakan.
ypercubeᵀᴹ
Gotcha. Saya sebenarnya bertanya apakah ada, karena saya memiliki pengalaman dengan RDBMS yang jauh lebih sedikit daripada yang saya bayangkan sebagian besar orang menjawab pertanyaan di situs ini;) Tapi itu adalah kecurigaan saya.
Adam Robinson
3
"Dan tidak dalam DBMS lain sejauh yang saya tahu." PostgreSQL 9.1 menambahkan fitur baru yang dirancang untuk tujuan ini. Ini lebih membatasi daripada implementasi MySQL.
Mark Byers
@MarkByers: thnx, saya tidak tahu itu.
ypercubeᵀᴹ
24

Selain solusi @ ypercube, "mengetik" tidak pernah menjadi alasan untuk menggunakan SELECT *. Saya sudah menulis tentang ini di sini , dan bahkan dengan solusinya saya pikir SELECTdaftar Anda masih harus menyertakan nama kolom - bahkan jika ada sejumlah besar seperti 40.

Singkatnya, Anda dapat menghindari mengetik daftar besar ini dengan mengklik dan menyeret simpul Kolom untuk objek di Object Explorer ke jendela kueri Anda. Cuplikan layar memperlihatkan tampilan tetapi hal yang sama dapat dilakukan untuk sebuah tabel.

masukkan deskripsi gambar di sini

Tetapi jika Anda ingin membaca tentang semua alasan mengapa Anda harus berusaha keras untuk menyeret item beberapa inci, silakan baca posting saya . :-)

Aaron Bertrand
sumber
Di PostgreSQL (dengan EMS SQL Manager), saya melakukan ini mendefinisikan tampilan SELECT *dan kemudian menyalin daftar bidang dari definisi tampilan.
dezso
Saya tentu setuju bahwa SELECT *tidak boleh digunakan. Saya ingin tahu tentang GROUP BYkasus ini. @ Harun, apakah ada masalah efisiensi dengan memiliki 40 kolom dalam daftar Group By?
ypercubeᵀᴹ
1
@ ypercube - Sejauh yang saya lihat jika Anda mengelompokkannya A.PK, A.some, A.other, A.columnstidak repot sebenarnya membandingkan some, other, columnsini hanya diperlukan oleh sintaks.
Martin Smith
1
@dagagod maaf, tidak, setiap celah hanya bisa dijelaskan oleh tim pengembang SSMS. :-)
Aaron Bertrand
1
@Pacerier Maaf, saya tidak setuju sepenuhnya , tapi mungkin Anda bisa menguraikan.
Aaron Bertrand