Apa tujuan utama penggunaan CROSS APPLY ?
Saya telah membaca (samar-samar, melalui posting di Internet) yang cross apply
bisa lebih efisien ketika memilih lebih dari set data besar jika Anda mempartisi. (Paging datang ke pikiran)
Saya juga tahu bahwa CROSS APPLY
tidak memerlukan UDF sebagai tabel kanan.
Dalam sebagian besar INNER JOIN
kueri (hubungan satu-ke-banyak), saya bisa menulis ulang untuk digunakan CROSS APPLY
, tetapi mereka selalu memberi saya rencana eksekusi yang setara.
Adakah yang bisa memberi saya contoh yang baik ketika CROSS APPLY
membuat perbedaan dalam kasus-kasus di mana INNER JOIN
akan bekerja juga?
Edit:
Berikut ini contoh sepele, di mana rencana eksekusi persis sama. (Tunjukkan satu di mana mereka berbeda dan di mana cross apply
lebih cepat / lebih efisien)
create table Company (
companyId int identity(1,1)
, companyName varchar(100)
, zipcode varchar(10)
, constraint PK_Company primary key (companyId)
)
GO
create table Person (
personId int identity(1,1)
, personName varchar(100)
, companyId int
, constraint FK_Person_CompanyId foreign key (companyId) references dbo.Company(companyId)
, constraint PK_Person primary key (personId)
)
GO
insert Company
select 'ABC Company', '19808' union
select 'XYZ Company', '08534' union
select '123 Company', '10016'
insert Person
select 'Alan', 1 union
select 'Bobby', 1 union
select 'Chris', 1 union
select 'Xavier', 2 union
select 'Yoshi', 2 union
select 'Zambrano', 2 union
select 'Player 1', 3 union
select 'Player 2', 3 union
select 'Player 3', 3
/* using CROSS APPLY */
select *
from Person p
cross apply (
select *
from Company c
where p.companyid = c.companyId
) Czip
/* the equivalent query using INNER JOIN */
select *
from Person p
inner join Company c on p.companyid = c.companyId
sumber
CROSS APPLY
memiliki penggunaan yang jelas dalam memungkinkan satu set untuk bergantung pada yang lain (tidak sepertiJOIN
operator), tetapi itu tidak datang tanpa biaya: itu berperilaku seperti fungsi yang beroperasi pada setiap anggota set kiri , jadi, dalam istilah SQL Server itu selalu melakukanLoop Join
, yang hampir tidak pernah merupakan cara terbaik untuk bergabung dengan set. Jadi, gunakanAPPLY
saat Anda perlu, tetapi jangan terlalu sering menggunakannyaJOIN
.Jawaban:
Lihat artikel di blog saya untuk perbandingan kinerja terperinci:
INNER JOIN
vs.CROSS APPLY
CROSS APPLY
bekerja lebih baik pada hal-hal yang tidak memilikiJOIN
kondisi sederhana .Yang ini memilih
3
catatan terakhir darit2
untuk setiap catatan darit1
:Itu tidak dapat dengan mudah dirumuskan dengan suatu
INNER JOIN
syarat.Anda mungkin dapat melakukan sesuatu seperti itu menggunakan
CTE
fungsi dan jendela:, tetapi ini kurang dapat dibaca dan mungkin kurang efisien.
Memperbarui:
Baru diperiksa.
master
adalah tabel tentang20,000,000
catatan denganPRIMARY KEY
onid
.Kueri ini:
berjalan selama hampir
30
detik, sementara yang ini:instan.
sumber
TVF
denganINNER JOIN
?CROSS APPLY
, ia meminta kapan harus memilihnyaINNER JOIN
, kapan itu akan berhasil juga.lateral join
dalam SQL standar (ANSI)cross apply
terkadang memungkinkan Anda untuk melakukan hal-hal yang tidak dapat Anda lakukaninner join
.Contoh (kesalahan sintaksis):
Ini adalah kesalahan sintaksis , karena, ketika digunakan dengan
inner join
, fungsi tabel hanya dapat mengambil variabel atau konstanta sebagai parameter. (Yaitu, parameter fungsi tabel tidak dapat bergantung pada kolom tabel lain.)Namun:
Ini legal.
Sunting: Atau sebagai alternatif, sintaksis lebih pendek: (oleh ErikE)
Edit:
Catatan: Informix 12.10 xC2 + memiliki Tabel Lateral Derived dan Postgresql (9.3+) memiliki Subqueries Lateral yang dapat digunakan untuk efek yang sama.
sumber
SELECT
diperlukan di dalamCROSS APPLY
. Silakan dicobaCROSS APPLY dbo.myTableFun(O.name) F
.Anggap Anda memiliki dua tabel.
Tabel MASTER
TABEL DETAIL
Ada banyak situasi di mana kita perlu mengganti
INNER JOIN
denganCROSS APPLY
.1. Gabung dua tabel berdasarkan
TOP n
hasilPertimbangkan apakah kita perlu memilih
Id
danName
dariMaster
dan dua tanggal terakhir untuk masing-masingId
dariDetails table
.Permintaan di atas menghasilkan hasil berikut.
Lihat, itu menghasilkan hasil untuk dua tanggal terakhir dengan dua tanggal terakhir
Id
dan kemudian bergabung dengan catatan ini hanya di permintaan luarId
, yang salah. Ini harus mengembalikanIds
1 dan 2 tetapi mengembalikan hanya 1 karena 1 memiliki dua tanggal terakhir. Untuk mencapai ini, kita perlu menggunakanCROSS APPLY
.dan membentuk hasil sebagai berikut.
Begini cara kerjanya. Kueri di dalam
CROSS APPLY
dapat merujuk tabel luar, di manaINNER JOIN
tidak bisa melakukan ini (itu melemparkan kesalahan kompilasi). Ketika menemukan dua tanggal terakhir, bergabung dilakukan di dalamCROSS APPLY
yaituWHERE M.ID=D.ID
,.2. Ketika kita membutuhkan
INNER JOIN
fungsionalitas menggunakan fungsi.CROSS APPLY
dapat digunakan sebagai penggantiINNER JOIN
ketika kita perlu mendapatkan hasil dariMaster
tabel dan afunction
.Dan inilah fungsinya
yang menghasilkan hasil berikut
KEUNTUNGAN TAMBAHAN LINTAS BERLAKU
APPLY
dapat digunakan sebagai penggantiUNPIVOT
. EntahCROSS APPLY
atauOUTER APPLY
dapat digunakan di sini, yang dapat dipertukarkan.Anggap Anda memiliki tabel di bawah ini (bernama
MYTABLE
).Kueri di bawah ini.
yang membawa Anda hasilnya
sumber
Tampak bagi saya bahwa CROSS BERLAKU dapat mengisi celah tertentu ketika bekerja dengan bidang terhitung dalam kueri kompleks / bersarang, dan membuatnya lebih sederhana dan lebih mudah dibaca.
Contoh sederhana: Anda memiliki DoB dan ingin menyajikan beberapa bidang yang berkaitan dengan usia yang juga akan bergantung pada sumber data lain (seperti pekerjaan), seperti Umur, AgeGroup, AgeAtHiring, MinimumRetirementDate, dll. Untuk digunakan dalam aplikasi pengguna akhir Anda (Excel PivotTables, misalnya).
Opsi terbatas dan jarang elegan:
BERGABUNG subqueries tidak dapat memperkenalkan nilai baru dalam dataset berdasarkan data dalam kueri induk (itu harus berdiri sendiri).
UDF rapi, tetapi lambat karena cenderung mencegah operasi paralel. Dan menjadi entitas yang terpisah dapat menjadi hal yang baik (kode kurang) atau buruk (di mana kode).
Tabel persimpangan. Kadang-kadang mereka dapat bekerja, tetapi segera Anda bergabung dengan subqueries dengan banyak UNION. Kekacauan besar.
Buat lagi tampilan tujuan tunggal, dengan anggapan perhitungan Anda tidak memerlukan data yang diperoleh di tengah jalan melalui permintaan utama Anda.
Tabel perantara. Ya ... itu biasanya bekerja, dan seringkali merupakan opsi yang baik karena dapat diindeks dan cepat, tetapi kinerja juga dapat turun karena pernyataan UPDATE tidak paralel dan tidak memungkinkan untuk mengalirkan rumus (menggunakan kembali hasil) untuk memperbarui beberapa bidang dalam pernyataan yang sama. Dan kadang-kadang Anda lebih suka melakukan hal-hal sekaligus.
Permintaan bersarang. Ya pada titik mana pun Anda dapat menempatkan tanda kurung di seluruh kueri Anda dan menggunakannya sebagai subquery tempat Anda dapat memanipulasi data sumber dan bidang yang dihitung sama. Tetapi Anda hanya bisa melakukan ini begitu banyak sebelum menjadi jelek. Sangat jelek.
Kode berulang. Apa nilai terbesar dari 3 pernyataan panjang (KASUS ... LAIN ... AKHIR)? Itu akan bisa dibaca!
Apakah saya melewatkan sesuatu? Mungkin, jadi jangan ragu untuk berkomentar. Tapi hei, LINTAS BERLAKU adalah seperti anugerah dalam situasi seperti: Anda hanya menambahkan sederhana
CROSS APPLY (select tbl.value + 1 as someFormula) as crossTbl
dan voila! Bidang baru Anda sekarang siap digunakan secara praktis seperti selalu ada di sumber data Anda.Nilai-nilai yang diperkenalkan melalui CROSS APPLY dapat ...
CROSS APPLY (select crossTbl.someFormula + 1 as someMoreFormula) as crossTbl2
Sial, tidak ada yang tidak bisa mereka lakukan!
sumber
Lintas berlaku berfungsi dengan baik dengan bidang XML juga. Jika Anda ingin memilih nilai simpul dalam kombinasi dengan bidang lain.
Misalnya, jika Anda memiliki tabel yang berisi beberapa xml
Menggunakan kueri
Akan mengembalikan hasilnya
sumber
Ini sudah dijawab dengan sangat baik secara teknis, tetapi izinkan saya memberikan contoh nyata bagaimana ini sangat berguna:
Katakanlah Anda memiliki dua tabel, Pelanggan dan Pesanan. Pelanggan memiliki banyak Pesanan.
Saya ingin membuat tampilan yang memberi saya detail tentang pelanggan, dan pesanan terbaru yang mereka buat. Hanya dengan BERGABUNG, ini akan membutuhkan beberapa penggabungan dan agregasi diri yang tidak cantik. Tetapi dengan Cross Apply, ini sangat mudah:
sumber
Cross apply dapat digunakan untuk menggantikan subquery di mana Anda memerlukan kolom subquery
subquery
di sini saya tidak akan dapat memilih kolom dari tabel perusahaan jadi, menggunakan lintas berlaku
sumber
Saya kira itu harus dibaca;)
LINTAS BERLAKU akan agak unik bagi orang yang membaca untuk memberi tahu mereka bahwa UDF sedang digunakan yang akan diterapkan ke setiap baris dari tabel di sebelah kiri.
Tentu, ada batasan lain di mana CROSS BERLAKU lebih baik digunakan daripada BERGABUNG dengan teman yang telah diposting di atas.
sumber
Berikut adalah artikel yang menjelaskan semuanya, dengan perbedaan kinerja dan penggunaannya di GABUNG.
SQL Server LINTAS BERLAKU dan OUTER BERLAKU LAGI
Seperti yang disarankan dalam artikel ini, tidak ada perbedaan kinerja di antara mereka untuk operasi join normal (INNER DAN CROSS).
Perbedaan penggunaan tiba ketika Anda harus melakukan kueri seperti ini:
Artinya, ketika Anda harus berhubungan dengan fungsi. Ini tidak dapat dilakukan menggunakan INNER JOIN, yang akan memberi Anda kesalahan "Pengidentifikasi multi-bagian" D.DepartmentID "tidak dapat diikat." Di sini nilainya diteruskan ke fungsi karena setiap baris dibaca. Kedengarannya keren bagiku. :)
sumber
Ya saya tidak yakin apakah ini memenuhi syarat sebagai alasan untuk menggunakan Cross Apply versus Inner Join, tetapi pertanyaan ini dijawab untuk saya di Post Forum menggunakan Cross Apply, jadi saya tidak yakin apakah ada metode equalivent menggunakan Inner Join:
SEBAGAI MULAI
AKHIR
sumber
Inti dari operator BERLAKU adalah untuk memungkinkan korelasi antara sisi kiri dan kanan operator dalam klausa FROM.
Berbeda dengan BERGABUNG, korelasi antara input tidak diperbolehkan.
Berbicara tentang korelasi di operator BERLAKU, maksud saya di sisi kanan kita dapat menempatkan:
Keduanya dapat mengembalikan beberapa kolom dan baris.
sumber
Ini mungkin pertanyaan lama, tapi saya masih suka kekuatan CROSS BERLAKU untuk menyederhanakan penggunaan kembali logika dan menyediakan mekanisme "rantai" untuk hasil.
Saya telah menyediakan SQL Fiddle di bawah ini yang menunjukkan contoh sederhana tentang bagaimana Anda dapat menggunakan CROSS APPLY untuk melakukan operasi logis kompleks pada set data Anda tanpa hal-hal yang berantakan sama sekali. Tidak sulit untuk memperkirakan dari sini perhitungan yang lebih kompleks.
http://sqlfiddle.com/#!3/23862/2
sumber
Sementara sebagian besar kueri yang menggunakan CROSS APPLY dapat ditulis ulang menggunakan INNER JOIN, CROSS APPLY dapat menghasilkan rencana eksekusi yang lebih baik dan kinerja yang lebih baik, karena dapat membatasi set yang bergabung belum sebelum bergabung terjadi.
Dicuri dari Sini
sumber