Kapan saya harus menggunakan cross apply pada inner join?

925

Apa tujuan utama penggunaan CROSS APPLY ?

Saya telah membaca (samar-samar, melalui posting di Internet) yang cross applybisa lebih efisien ketika memilih lebih dari set data besar jika Anda mempartisi. (Paging datang ke pikiran)

Saya juga tahu bahwa CROSS APPLYtidak memerlukan UDF sebagai tabel kanan.

Dalam sebagian besar INNER JOINkueri (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 APPLYmembuat perbedaan dalam kasus-kasus di mana INNER JOINakan bekerja juga?


Edit:

Berikut ini contoh sepele, di mana rencana eksekusi persis sama. (Tunjukkan satu di mana mereka berbeda dan di mana cross applylebih 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
Jeff Meatball Yang
sumber
50
Saya tahu ini BAHKAN PICKIER dari saya tetapi 'pemain' adalah kata yang paling tepat. Itu tidak terkait dengan efisiensi.
Rire1979
2
Ini sangat berguna untuk sql xquery. periksa ini .
ARZ
3
Sepertinya menggunakan "inner loop join" akan sangat dekat dengan cross berlaku. Saya berharap contoh Anda rinci yang bergabung dengan petunjuk itu setara. Hanya dengan mengatakan bergabung dapat mengakibatkan inner / loop / merge atau bahkan "lain" karena dapat mengatur ulang dengan bergabung lainnya.
crokusek
3
Ketika bergabung akan membuat banyak baris tetapi Anda hanya perlu mengevaluasi satu baris bergabung sekaligus. Saya punya kasing kalau saya perlu bergabung sendiri di atas meja dengan lebih dari 100 juta baris dan ada memori yang tidak cukup. Jadi saya pergi kursor untuk membawa jejak memori ke bawah. Dari kursor saya beralih silang menerapkan jejak memori yang masih dikelola dan 1/3 lebih cepat dari kursor.
paparazzo
10
CROSS APPLYmemiliki penggunaan yang jelas dalam memungkinkan satu set untuk bergantung pada yang lain (tidak seperti JOINoperator), tetapi itu tidak datang tanpa biaya: itu berperilaku seperti fungsi yang beroperasi pada setiap anggota set kiri , jadi, dalam istilah SQL Server itu selalu melakukan Loop Join, yang hampir tidak pernah merupakan cara terbaik untuk bergabung dengan set. Jadi, gunakan APPLYsaat Anda perlu, tetapi jangan terlalu sering menggunakannya JOIN.
Gerardo Lima

Jawaban:

668

Adakah yang bisa memberi saya contoh yang bagus ketika CROSS BERLAKU membuat perbedaan dalam kasus-kasus di mana INNER BERGABUNG juga bekerja?

Lihat artikel di blog saya untuk perbandingan kinerja terperinci:

CROSS APPLYbekerja lebih baik pada hal-hal yang tidak memiliki JOINkondisi sederhana .

Yang ini memilih 3catatan terakhir dari t2untuk setiap catatan dari t1:

SELECT  t1.*, t2o.*
FROM    t1
CROSS APPLY
        (
        SELECT  TOP 3 *
        FROM    t2
        WHERE   t2.t1_id = t1.id
        ORDER BY
                t2.rank DESC
        ) t2o

Itu tidak dapat dengan mudah dirumuskan dengan suatu INNER JOINsyarat.

Anda mungkin dapat melakukan sesuatu seperti itu menggunakan CTEfungsi dan jendela:

WITH    t2o AS
        (
        SELECT  t2.*, ROW_NUMBER() OVER (PARTITION BY t1_id ORDER BY rank) AS rn
        FROM    t2
        )
SELECT  t1.*, t2o.*
FROM    t1
INNER JOIN
        t2o
ON      t2o.t1_id = t1.id
        AND t2o.rn <= 3

, tetapi ini kurang dapat dibaca dan mungkin kurang efisien.

Memperbarui:

Baru diperiksa.

masteradalah tabel tentang 20,000,000catatan dengan PRIMARY KEYon id.

Kueri ini:

WITH    q AS
        (
        SELECT  *, ROW_NUMBER() OVER (ORDER BY id) AS rn
        FROM    master
        ),
        t AS 
        (
        SELECT  1 AS id
        UNION ALL
        SELECT  2
        )
SELECT  *
FROM    t
JOIN    q
ON      q.rn <= t.id

berjalan selama hampir 30detik, sementara yang ini:

WITH    t AS 
        (
        SELECT  1 AS id
        UNION ALL
        SELECT  2
        )
SELECT  *
FROM    t
CROSS APPLY
        (
        SELECT  TOP (t.id) m.*
        FROM    master m
        ORDER BY
                id
        ) q

instan.

Quassnoi
sumber
2
Lihat akhir tautan Ariel. Queri row_number () sama bagusnya dan bahkan tidak memerlukan join. Jadi saya tidak berpikir saya harus menggunakan cross apply untuk situasi ini (pilih top 3, partisi oleh t1.id).
Jeff Meatball Yang
375
Meskipun ini adalah jawaban yang paling populer, saya tidak berpikir itu menjawab pertanyaan yang sebenarnya "Apa tujuan utama menggunakan CROSS BERLAKU?". Tujuan utamanya adalah untuk mengaktifkan fungsi tabel dengan parameter yang akan dieksekusi satu kali per baris dan kemudian bergabung dengan hasilnya.
MikeKulls
5
@ Mike: bagaimana Anda menelepon TVFdengan INNER JOIN?
Quassnoi
15
@MikeKulls Ya, tetapi OP tidak meminta tujuan utama penggunaan CROSS APPLY, ia meminta kapan harus memilihnya INNER JOIN, kapan itu akan berhasil juga.
ErikE
8
Mungkin perlu disebutkan bahwa ini disebut lateral joindalam SQL standar (ANSI)
a_horse_with_no_name
198

cross applyterkadang memungkinkan Anda untuk melakukan hal-hal yang tidak dapat Anda lakukan inner join.

Contoh (kesalahan sintaksis):

select F.* from sys.objects O  
inner join dbo.myTableFun(O.name) F   
on F.schema_id= O.schema_id

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:

select F.* from sys.objects O  
cross apply ( select * from dbo.myTableFun(O.name) ) F  
where F.schema_id= O.schema_id

Ini legal.

Sunting: Atau sebagai alternatif, sintaksis lebih pendek: (oleh ErikE)

select F.* from sys.objects O  
cross apply dbo.myTableFun(O.name) F
where F.schema_id= O.schema_id

Edit:

Catatan: Informix 12.10 xC2 + memiliki Tabel Lateral Derived dan Postgresql (9.3+) memiliki Subqueries Lateral yang dapat digunakan untuk efek yang sama.

nurettin
sumber
11
Saya pikir ini adalah alasan di balik mengapa kita harus berlaku silang. Jika Anda melihat tautan di bawah ini adalah hal pertama yang dikatakan MS tentang cross berlaku. Mungkin ada kegunaan lain tapi saya pikir ini adalah alasan itu diperkenalkan. Tanpa itu fungsi tabel tidak akan dapat digunakan dalam banyak situasi. technet.microsoft.com/en-us/library/ms175156.aspx
MikeKulls
cross apply juga menghasilkan rencana eksekusi yang bagus ketika digabungkan dengan fungsi tabel inline sambil mempertahankan modularitas yang sangat dibutuhkan.
nurettin
14
Tidak SELECTdiperlukan di dalam CROSS APPLY. Silakan dicoba CROSS APPLY dbo.myTableFun(O.name) F.
ErikE
1
@ErikE yakin, Anda selalu dapat menggunakan sintaks yang kurang fleksibel untuk berlaku silang. Saya menunjukkan versi yang lebih umum yang kadang-kadang bisa Anda gunakan untuk menghindari kesulitan menghitung kolom ke dalam kueri.
nurettin
2
@Bolu inner join tidak akan berfungsi jika parameter fungsi tabel bergantung pada kolom tabel lain (alias referensi eksternal) pada pemilihan eksternal. Ini akan berfungsi jika parameter fungsi tabel adalah literal atau variabel. Palang berlaku akan bekerja dalam kedua kasus.
nurettin
175

Anggap Anda memiliki dua tabel.

Tabel MASTER

x------x--------------------x
| Id   |        Name        |
x------x--------------------x
|  1   |          A         |
|  2   |          B         |
|  3   |          C         |
x------x--------------------x

TABEL DETAIL

x------x--------------------x-------x
| Id   |      PERIOD        |   QTY |
x------x--------------------x-------x
|  1   |   2014-01-13       |   10  |
|  1   |   2014-01-11       |   15  |
|  1   |   2014-01-12       |   20  |
|  2   |   2014-01-06       |   30  |
|  2   |   2014-01-08       |   40  |
x------x--------------------x-------x

Ada banyak situasi di mana kita perlu mengganti INNER JOINdengan CROSS APPLY.

1. Gabung dua tabel berdasarkan TOP nhasil

Pertimbangkan apakah kita perlu memilih Iddan Namedari Masterdan dua tanggal terakhir untuk masing-masing Iddari Details table.

SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
INNER JOIN
(
    SELECT TOP 2 ID, PERIOD,QTY 
    FROM DETAILS D      
    ORDER BY CAST(PERIOD AS DATE)DESC
)D
ON M.ID=D.ID

Permintaan di atas menghasilkan hasil berikut.

x------x---------x--------------x-------x
|  Id  |   Name  |   PERIOD     |  QTY  |
x------x---------x--------------x-------x
|   1  |   A     | 2014-01-13   |  10   |
|   1  |   A     | 2014-01-12   |  20   |
x------x---------x--------------x-------x

Lihat, itu menghasilkan hasil untuk dua tanggal terakhir dengan dua tanggal terakhir Iddan kemudian bergabung dengan catatan ini hanya di permintaan luar Id, yang salah. Ini harus mengembalikan Ids1 dan 2 tetapi mengembalikan hanya 1 karena 1 memiliki dua tanggal terakhir. Untuk mencapai ini, kita perlu menggunakan CROSS APPLY.

SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
CROSS APPLY
(
    SELECT TOP 2 ID, PERIOD,QTY 
    FROM DETAILS D  
    WHERE M.ID=D.ID
    ORDER BY CAST(PERIOD AS DATE)DESC
)D

dan membentuk hasil sebagai berikut.

x------x---------x--------------x-------x
|  Id  |   Name  |   PERIOD     |  QTY  |
x------x---------x--------------x-------x
|   1  |   A     | 2014-01-13   |  10   |
|   1  |   A     | 2014-01-12   |  20   |
|   2  |   B     | 2014-01-08   |  40   |
|   2  |   B     | 2014-01-06   |  30   |
x------x---------x--------------x-------x

Begini cara kerjanya. Kueri di dalam CROSS APPLYdapat merujuk tabel luar, di mana INNER JOINtidak bisa melakukan ini (itu melemparkan kesalahan kompilasi). Ketika menemukan dua tanggal terakhir, bergabung dilakukan di dalam CROSS APPLYyaitu WHERE M.ID=D.ID,.

2. Ketika kita membutuhkan INNER JOINfungsionalitas menggunakan fungsi.

CROSS APPLYdapat digunakan sebagai pengganti INNER JOINketika kita perlu mendapatkan hasil dari Mastertabel dan a function.

SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
CROSS APPLY dbo.FnGetQty(M.ID) C

Dan inilah fungsinya

CREATE FUNCTION FnGetQty 
(   
    @Id INT 
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT ID,PERIOD,QTY 
    FROM DETAILS
    WHERE ID=@Id
)

yang menghasilkan hasil berikut

x------x---------x--------------x-------x
|  Id  |   Name  |   PERIOD     |  QTY  |
x------x---------x--------------x-------x
|   1  |   A     | 2014-01-13   |  10   |
|   1  |   A     | 2014-01-11   |  15   |
|   1  |   A     | 2014-01-12   |  20   |
|   2  |   B     | 2014-01-06   |  30   |
|   2  |   B     | 2014-01-08   |  40   |
x------x---------x--------------x-------x

KEUNTUNGAN TAMBAHAN LINTAS BERLAKU

APPLYdapat digunakan sebagai pengganti UNPIVOT. Entah CROSS APPLYatau OUTER APPLYdapat digunakan di sini, yang dapat dipertukarkan.

Anggap Anda memiliki tabel di bawah ini (bernama MYTABLE).

x------x-------------x--------------x
|  Id  |   FROMDATE  |   TODATE     |
x------x-------------x--------------x
|   1  |  2014-01-11 | 2014-01-13   | 
|   1  |  2014-02-23 | 2014-02-27   | 
|   2  |  2014-05-06 | 2014-05-30   | 
|   3  |     NULL    |    NULL      |
x------x-------------x--------------x

Kueri di bawah ini.

SELECT DISTINCT ID,DATES
FROM MYTABLE 
CROSS APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)

yang membawa Anda hasilnya

  x------x-------------x
  | Id   |    DATES    |
  x------x-------------x
  |  1   |  2014-01-11 |
  |  1   |  2014-01-13 |
  |  1   |  2014-02-23 |
  |  1   |  2014-02-27 |
  |  2   |  2014-05-06 |
  |  2   |  2014-05-30 | 
  |  3   |    NULL     | 
  x------x-------------x
Sarath Avanavu
sumber
4
Contoh yang sangat baik dengan catatan 2 vs 4 dan membantu saya memahami konteks di mana ini akan dibutuhkan.
trnelson
13
Jawaban ini membuktikan bahwa benar-benar layak untuk menggulir ke bawah halaman alih-alih hanya untuk memilih yang diterima.
Mostafa Armandi
2
Contoh terbaik sejauh ini untuk menjelaskan penggunaan BERLAKU ... Saya telah membaca banyak posting dan menyadari bahwa penjelasan ini membersihkan gambar sebagai air. Terima kasih banyak kawan.
AG7
1
Untuk titik 1 di mana kita memiliki 2 baris untuk ID 1, bukan 4 baris untuk ID 1, 2. Bukankah kita hanya akan menggunakan gabung kiri.
Joseph Cho
43

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!

    • Beri tahu klien Anda untuk menghitung sendiri.

Apakah saya melewatkan sesuatu? Mungkin, jadi jangan ragu untuk berkomentar. Tapi hei, LINTAS BERLAKU adalah seperti anugerah dalam situasi seperti: Anda hanya menambahkan sederhanaCROSS 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 ...

  • digunakan untuk membuat satu atau beberapa bidang terhitung tanpa menambahkan masalah kinerja, kompleksitas atau keterbacaan ke dalam campuran
  • seperti dengan BERGABUNG, beberapa pernyataan BERLAKU LINTAS berikutnya dapat merujuk pada diri mereka sendiri: CROSS APPLY (select crossTbl.someFormula + 1 as someMoreFormula) as crossTbl2
  • Anda dapat menggunakan nilai yang diperkenalkan oleh CROSS BERLAKU dalam kondisi BERGABUNG berikutnya
  • Sebagai bonus, ada aspek fungsi yang dihargai Tabel

Sial, tidak ada yang tidak bisa mereka lakukan!

mtone
sumber
1
Ini adalah +1 besar dari saya, karena saya terkejut itu tidak disebutkan lebih sering. Mungkin Anda bisa memperluas contoh ini untuk menunjukkan bagaimana Anda dapat melakukan perhitungan "prosedural" pada rantai nilai turunan? Contoh: CROSS APPLY (pilih crossTbl.value * tbl.multiplier as Multiplied) multiTbl - CROSS APPLY (pilih multiTbl. Multi / blbl. Multi-Ratio as Derived) derivatedTbl - etc ...
mrmillsy
1
Adakah lagi info / contoh tentang cara menggunakan Cross Apply sebagai pengganti CASE..ELSE..END?
przemo_li
3
@przemo_li BERLAKU dapat digunakan untuk menyimpan hasil dari pernyataan kasus (antara lain) untuk merujuknya. Struktur dapat berupa: SELECT CASE ketika subquery.intermediateResult> 0 THEN "yes" ELSE "no" END DARI someTable OUTER BERLAKU (pilih CASE ... END ... ELSE sebagai intermediateResult) sebagai subquery.
mtone
14

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

<root>
    <subnode1>
       <some_node value="1" />
       <some_node value="2" />
       <some_node value="3" />
       <some_node value="4" />
    </subnode1>
</root>

Menggunakan kueri

SELECT
       id as [xt_id]
      ,xmlfield.value('(/root/@attribute)[1]', 'varchar(50)') root_attribute_value
  ,node_attribute_value = [some_node].value('@value', 'int')
  ,lt.lt_name   
FROM dbo.table_with_xml xt
CROSS APPLY xmlfield.nodes('/root/subnode1/some_node') as g ([some_node])
LEFT OUTER JOIN dbo.lookup_table lt
ON [some_node].value('@value', 'int') = lt.lt_id

Akan mengembalikan hasilnya

xt_id root_attribute_value node_attribute_value lt_name
----------------------------------------------------------------------
1     test1            1                    Benefits
1     test1            4                    FINRPTCOMPANY
Chris
sumber
13

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:

SELECT *
FROM Customer
CROSS APPLY (
  SELECT TOP 1 *
  FROM Order
  WHERE Order.CustomerId = Customer.CustomerId
  ORDER BY OrderDate DESC
) T
Apneal
sumber
7

Cross apply dapat digunakan untuk menggantikan subquery di mana Anda memerlukan kolom subquery

subquery

select * from person p where
p.companyId in(select c.companyId from company c where c.companyname like '%yyy%')

di sini saya tidak akan dapat memilih kolom dari tabel perusahaan jadi, menggunakan lintas berlaku

select P.*,T.CompanyName
from Person p
cross apply (
    select *
    from Company C
    where p.companyid = c.companyId and c.CompanyName like '%yyy%'
) T
balaji dileep kumar
sumber
5

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.

shahkalpesh
sumber
4

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

masukkan deskripsi gambar di sini

Perbedaan penggunaan tiba ketika Anda harus melakukan kueri seperti ini:

CREATE FUNCTION dbo.fn_GetAllEmployeeOfADepartment(@DeptID AS INT)  
RETURNS TABLE 
AS 
RETURN 
   ( 
   SELECT * FROM Employee E 
   WHERE E.DepartmentID = @DeptID 
   ) 
GO 
SELECT * FROM Department D 
CROSS APPLY dbo.fn_GetAllEmployeeOfADepartment(D.DepartmentID)

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. :)

Shanid
sumber
3

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:

Create PROCEDURE [dbo].[Message_FindHighestMatches]

-- Declare the Topical Neighborhood
@TopicalNeighborhood nchar(255)

SEBAGAI MULAI

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON

Create table  #temp
(
    MessageID         int,
    Subjects          nchar(255),
    SubjectsCount    int
)

Insert into #temp Select MessageID, Subjects, SubjectsCount From Message

Select Top 20 MessageID, Subjects, SubjectsCount,
    (t.cnt * 100)/t3.inputvalues as MatchPercentage

From #temp 

cross apply (select count(*) as cnt from dbo.Split(Subjects,',') as t1
             join dbo.Split(@TopicalNeighborhood,',') as t2
             on t1.value = t2.value) as t
cross apply (select count(*) as inputValues from dbo.Split(@TopicalNeighborhood,',')) as t3

Order By MatchPercentage desc

drop table #temp

AKHIR

pengguna1054326
sumber
3

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:

  • tabel turunan - sebagai subquery berkorelasi dengan alias
  • fungsi bernilai tabel - tampilan konseptual dengan parameter, di mana parameter dapat merujuk ke sisi kiri

Keduanya dapat mengembalikan beberapa kolom dan baris.

Raf
sumber
2

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

mrmillsy
sumber
1

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

Greg Gum
sumber