Saya akan menggunakan contoh konkret, tetapi hipotetis.
Setiap pesanan biasanya hanya memiliki satu item baris :
Pesanan:
OrderGUID OrderNumber
========= ============
{FFB2...} STL-7442-1
{3EC6...} MPT-9931-8A
Item Baris:
LineItemGUID Order ID Quantity Description
============ ======== ======== =================================
{098FBE3...} 1 7 prefabulated amulite
{1609B09...} 2 32 spurving bearing
Tetapi kadang-kadang akan ada pesanan dengan dua item baris:
LineItemID Order ID Quantity Description
========== ======== ======== =================================
{A58A1...} 6,784,329 5 pentametric fan
{0E9BC...} 6,784,329 5 differential girdlespring
Biasanya ketika menampilkan pesanan kepada pengguna:
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN LineItems
ON Orders.OrderID = LineItems.OrderID
Saya ingin menunjukkan satu item pada pesanan. Tapi dengan pesanan sesekali ini mengandung dua (atau lebih) item, perintah akan muncul akan digandakan :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 spurving bearing
KSG-0619-81 5 panametric fan
KSG-0619-81 5 differential girdlespring
Yang benar-benar saya inginkan adalah memiliki SQL Server hanya memilih satu , karena akan cukup baik :
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan
Jika saya suka bertualang, saya mungkin menunjukkan kepada pengguna, sebuah elipsis untuk menunjukkan bahwa ada lebih dari satu:
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan, ...
Jadi pertanyaannya adalah bagaimana caranya
- menghilangkan baris "duplikat"
- hanya bergabung ke salah satu baris, untuk menghindari duplikasi
Percobaan pertama
Upaya naif pertama saya adalah hanya bergabung dengan item baris " TOP 1 ":
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN (
SELECT TOP 1 LineItems.Quantity, LineItems.Description
FROM LineItems
WHERE LineItems.OrderID = Orders.OrderID) LineItems2
ON 1=1
Tapi itu memberi kesalahan:
Kolom atau awalan 'Pesanan' tidak
cocok dengan nama tabel atau nama alias yang
digunakan dalam kueri.
Agaknya karena seleksi dalam tidak melihat tabel luar.
sumber
group by
?group by
akan membutuhkan daftar semua kolom lainnya, kecuali kolom yang tidak Anda inginkan duplikatnya. SumberJawaban:
Di SQL Server 2005 dan di atas, Anda bisa mengganti
INNER JOIN
denganCROSS APPLY
:Harap perhatikan bahwa
TOP 1
tanpaORDER BY
itu tidak deterministik: kueri ini akan membuat Anda mendapatkan satu item baris per pesanan, tetapi tidak ditentukan yang mana.Berbagai permintaan kueri dapat memberi Anda item baris berbeda untuk urutan yang sama, bahkan jika yang mendasarinya tidak berubah.
Jika Anda ingin urutan deterministik, Anda harus menambahkan
ORDER BY
klausa ke permintaan paling dalam.sumber
CROSS APPLY
sebaliknyaINNER JOIN
danOUTER APPLY
sebaliknyaLEFT JOIN
(sama sepertiLEFT OUTER JOIN
).Saya tahu pertanyaan ini dijawab beberapa saat yang lalu, tetapi ketika berhadapan dengan set data besar, query yang disarangkan bisa mahal. Berikut adalah solusi berbeda di mana kueri bersarang hanya akan dijalankan sekali, alih-alih untuk setiap baris yang dikembalikan.
sumber
Anda bisa melakukannya:
Ini membutuhkan indeks (atau kunci utama)
LineItems.LineItemID
dan indeks aktifLineItems.OrderID
atau akan lambat.sumber
LineItems.LineItemID = null
dan menghapus pesanan entitas kiri sepenuhnya dari hasilnya.@Quassnoi jawaban baik, dalam beberapa kasus (terutama jika tabel luar besar), kueri yang lebih efisien mungkin dengan menggunakan fungsi berjendela, seperti ini:
Terkadang Anda hanya perlu menguji kueri mana yang memberikan kinerja lebih baik.
sumber
, Pendekatan lain yang menggunakan ekspresi tabel umum:
atau, pada akhirnya mungkin Anda ingin menunjukkan semua baris bergabung?
versi yang dipisahkan koma di sini:
sumber
Dari SQL Server 2012 dan selanjutnya saya pikir ini akan melakukan trik:
sumber
Sub kueri yang terkait adalah sub kueri yang bergantung pada kueri luar. Ini seperti for loop dalam SQL. Sub-kueri akan dijalankan satu kali untuk setiap baris di kueri luar:
sumber
EDIT: tidak apa-apa, Quassnoi memiliki jawaban yang lebih baik.
Untuk SQL2K, sesuatu seperti ini:
sumber
Cara favorit saya untuk menjalankan kueri ini adalah dengan klausa yang tidak ada. Saya percaya ini adalah cara paling efisien untuk menjalankan kueri semacam ini:
Tapi saya belum menguji metode ini terhadap metode lain yang disarankan di sini.
sumber
Mencoba salib, bekerja dengan baik, tetapi membutuhkan waktu sedikit lebih lama. Kolom baris yang disesuaikan memiliki grup maks dan ditambahkan yang menjaga kecepatan dan menjatuhkan catatan tambahan.
Inilah kueri yang disesuaikan:
sumber
coba ini
sumber