İç birleşim yerine çapraz uygulamayı ne zaman kullanmalıyım?


925

ÇAPRAZ UYGULAMAYI kullanmanın temel amacı nedir ?

Ben cross applybölümleme ise büyük veri kümeleri üzerinde seçim yaparken daha verimli olabilir (belirsiz, Internet posta yoluyla) okudum . (Sayfalama akla geliyor)

Ayrıca CROSS APPLYsağ tablo olarak bir UDF gerektirmediğini de biliyorum .

Çoğu INNER JOINsorguda (bire çok ilişkiler), bunları kullanmak için yeniden yazabilirim CROSS APPLY, ancak her zaman bana eşdeğer yürütme planları veriyorlar.

Biri işe yarayacağı CROSS APPLYdurumlarda ne zaman fark yarattığına dair iyi bir örnek verebilir INNER JOINmi?


Düzenle:

İcra planlarının tamamen aynı olduğu önemsiz bir örnek. (Bana nerede farklı olduklarını ve nerede cross applydaha hızlı / daha verimli olduğunu gösterin )

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

50
Biliyorum bu benim BİLE SEÇMELİ ama 'performans' kesinlikle bir kelimedir. Sadece verimlilikle ilgili değil.
Rire1979

2
Sql xquery için çok kullanışlıdır. kontrol bu .
ARZ

3
Görünüşe göre "iç döngü birleştirme" çapraz uygulama çok yakın olurdu. Örneğin, hangi birleştirme ipucunun eşdeğer olduğunu ayrıntılı bir şekilde diliyorum. Sadece birleştirme demek iç / döngü / birleştirme veya "diğer" ile sonuçlanabilir, çünkü diğer birleşimlerle yeniden düzenlenebilir.
crokusek

3
Birleştirme çok sayıda satır oluşturacak ancak bir kerede yalnızca bir satır birleştirmeyi değerlendirmeniz gerekir. 100 milyondan fazla satır içeren bir masaya kendi kendine katılmam gerekiyordu ve yeterli bellek yoktu. Bu yüzden bellek ayak izini azaltmak için imleçe gittim. İmleçten geçip hala yönetilen bellek ayak izi olarak uyguladım ve imleçten 1/3 daha hızlıydı.
paparazzo

10
CROSS APPLYbir kümenin diğerine ( JOINoperatörün aksine ) bağımlı olmasına izin veren bariz kullanımı vardır , ancak bu bir maliyet olmadan gelmez: sol kümenin her üyesi üzerinde çalışan bir işlev gibi davranır , bu nedenle SQL Server terimleriyle her zaman bir Loop Joinset gerçekleştirin , ki bu neredeyse hiçbir zaman setlere katılmanın en iyi yoludur. Bu nedenle, APPLYihtiyacınız olduğunda kullanın, ancak aşırı kullanmayın JOIN.
Gerardo Lima

Yanıtlar:


667

INNER JOIN'in de çalışacağı durumlarda kimse CROSS UYGULAMA'nın ne zaman bir fark yarattığına dair iyi bir örnek verebilir mi?

Ayrıntılı performans karşılaştırması için blogumdaki makaleye bakın:

CROSS APPLYbasit bir JOINşartı olmayan şeylerde daha iyi çalışır .

Bu , her bir kayıt için 3son kayıtları aşağıdakilerden seçer :t2t1

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

Bir INNER JOINkoşulla kolayca formüle edilemez .

CTE'S ve window işlevini kullanarak muhtemelen böyle bir şey yapabilirsiniz :

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

, ancak bu daha az okunabilir ve muhtemelen daha az verimlidir.

Güncelleme:

Yeni kontrol edildi.

masteryaklaşık bir tablodur 20,000,000bir ile kayıtları PRIMARY KEYüzerinde id.

Bu sorgu:

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

neredeyse 30saniyeler boyunca çalışır , bu ise:

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

anında.


2
Ariel bağlantısının sonuna bakın. Bir row_number () sorgusu da aynı derecede güzeldir ve birleştirme gerektirmez. Bu yüzden bu durum için çapraz uygulama kullanmam gerektiğini düşünmüyorum.
Jeff Meatball Yang

375
Her ne kadar bu en popüler cevap olsa da, "ÇAPRAZ UYGULAMAYI kullanmanın temel amacı nedir?" Temel amaç, parametreler içeren tablo işlevlerinin her satırda bir kez yürütülmesini ve sonuçlara birleştirilmesini sağlamaktır.
MikeKulls

5
@ Mike: nasıl bir diyorsunuz TVFile INNER JOIN?
Quassnoi

15
@MikeKulls Evet, ancak OP ana kullanım amacını CROSS APPLYsormadı, ne zaman seçileceğini INNER JOIN, ne zaman işe yarayacağını sordu .
ErikE

8
Buna lateral joinstandart (ANSI) SQL'de denir
a_horse_with_no_name

198

cross applybazen yapamayacağınız şeyleri yapmanızı sağlar inner join.

Örnek (bir sözdizimi hatası):

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

Bu, bir sözdizimi hatasıdır , çünkü inner jointablo işlevleriyle birlikte kullanıldığında değişkenleri veya sabitleri parametre olarak alabilir . (Yani, tablo işlevi parametresi başka bir tablonun sütununa bağlı olamaz.)

Ancak:

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

Bu yasal.

Düzenleme: Veya alternatif olarak, daha kısa sözdizimi: (ErikE tarafından)

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

Düzenle:

Not: Informix 12.10 xC2 + 'ın Lateral Türetilmiş Tabloları vardır ve Postgresql (9.3+) benzer bir efekt için kullanılabilen Lateral Alt Sorgulara sahiptir .


11
Sanırım çapraz başvurumuzun ardındaki sebep bu. Aşağıdaki bağlantıya bakarsanız, MS'nin çapraz uygulama hakkında söylediği ilk şey budur. Başka kullanımları olabilir ama bence bu tanıtıldı. Bu olmadan tablo işlevleri pek çok durumda kullanılamaz. technet.microsoft.com/en-us/library/ms175156.aspx
MikeKulls

çapraz uygulama ayrıca çok fazla modülerliği korurken, satır içi tablo işlevleriyle birleştiğinde güzel bir yürütme planı oluşturur.
nurettin

14
SELECTİçinde gerek yok CROSS APPLY. Lütfen deneyin CROSS APPLY dbo.myTableFun(O.name) F.
ErikE

1
Emin olun, çapraz uygulama için her zaman daha az esnek sözdizimini kullanabilirsiniz. Sorguya zor hesaplama sütunları getirmekten kaçınmak için bazen kullanabileceğiniz daha genelleştirilmiş sürümünü gösteriyordum.
nurettin

2
@Bolu iç birleşimi, tablo işlev parametresi harici seçimdeki başka bir tablonun sütununa (diğer adıyla harici başvuru) bağlıysa çalışmaz. Table işlev parametresi değişmez ya da değişkense çalışır. Çapraz uygulama her iki durumda da işe yarayacaktır.
nurettin

175

İki tablonuz olduğunu düşünün.

MASTER MASA

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

DETAYLAR TABLOSU

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

Değiştirmemiz gereken birçok durum INNER JOINvar CROSS APPLY.

1. TOP nSonuçlara göre iki tabloya katılın

Biz belirlemeniz gerekirse düşünün Idve Namegelen Masterbiri için ve son iki tarihleri Idarasından 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

Yukarıdaki sorgu aşağıdaki sonucu oluşturur.

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

Bakın, son iki tarih için son iki tarih için sonuçlar üretti Idve daha sonra bu kayıtları yalnızca üzerindeki dış sorguda birleştirdi Id, bu yanlış. Bu hem Ids1 hem de 2 değerini döndürüyor olmalıdır, ancak 1 yalnızca son iki tarihe sahip olduğu için yalnızca 1 döndürdü. Bunu başarmak için kullanmamız gerekir 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

ve aşağıdaki sonucu oluşturur.

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

İşte böyle. İçindeki sorgu CROSS APPLY, INNER JOINbunu yapamayan dış tabloya başvurabilir (derleme hatası atar). Son iki tarih bulunurken, katılma, CROSS APPLYyani içinde yapılır WHERE M.ID=D.ID.

2. INNER JOINİşlevleri kullanarak işleve ihtiyaç duyduğumuzda .

CROSS APPLYtablodan INNER JOINsonuç almamız gerektiğinde yedek olarak kullanılabilir Masterve a function.

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

Ve işte fonksiyon

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

Aşağıdaki sonucu verdi

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

ÇAPRAZ UYGULAMANIN EK AVANTAJLARI

APPLYyerine kullanılabilir UNPIVOT. Ya CROSS APPLYya OUTER APPLYbirbirlerinin yerine hangi burada kullanılabilir.

Aşağıdaki tabloya (adlandırılmış MYTABLE) sahip olduğunuzu düşünün .

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

Sorgu aşağıdadır.

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

bu da sonucu getirir

  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

4
2'ye 4 kayıtları ile mükemmel bir örnek ve bunun gerekli olduğu bağlamı anlamama yardımcı oldu.
trnelson

13
Bu cevap, kabul edileni seçmek yerine sayfayı aşağı kaydırmanın gerçekten değerli olduğunu kanıtlıyor.
Mostafa Armandi

2
UYGULAMA kullanımını açıklamak için şimdiye kadarki en iyi örnek ... Birçok yazı okudum ve bu açıklamanın resmi su olarak temizlediğinin farkındayım. Çok teşekkürler kardeşim.
AG7

1
Kimlik 1, 2 için 4 satır yerine Kimlik 1 için 2 satırımız olan 1. nokta için, bunun yerine yalnızca sol birleştirme kullanmaz mıyız.
Joseph Cho

43

Bana öyle geliyor ki, ÇAPRAZ UYGULAMA karmaşık / iç içe sorgularda hesaplanan alanlarla çalışırken belirli bir boşluğu doldurabilir ve bunları daha basit ve daha okunabilir hale getirebilir.

Basit bir örnek: bir DoB'niz var ve son kullanıcı uygulamanızda kullanmak için Yaş, AgeGroup, AgeAtHiring, MinimumRetirementDate vb. Gibi diğer veri kaynaklarına (istihdam gibi) da dayanan, yaşa bağlı birden çok alan sunmak istiyorsunuz. (Örneğin Excel PivotTable'ları).

Seçenekler sınırlıdır ve nadiren zariftir:

  • JOIN alt sorguları, üst sorgudaki verilere dayanarak veri kümesine yeni değerler ekleyemez (tek başına durmalıdır).

  • UDF'ler düzgün, ancak paralel işlemleri önleme eğiliminde oldukları için yavaştır. Ayrı bir varlık olmak, iyi (daha az kod) veya kötü (kodun nerede olduğu) bir şey olabilir.

  • Bağlantı tabloları. Bazen işe yarayabilirler, ancak yeterince yakında tonlarca UNION ile alt sorgulara katılıyorsunuz. Büyük karışıklık.

  • Hesaplarınızın ana sorgunuzun ortasında elde edilen verileri gerektirmediğini varsayarak başka bir tek amaçlı görünüm oluşturun.

  • Aracı tabloları. Evet ... genellikle işe yarıyor ve dizine eklenip hızlı bir şekilde kullanılabildikleri için iyi bir seçenek. aynı ifade. Ve bazen sadece bir geçişte bir şeyler yapmayı tercih edersiniz.

  • Yuvalama sorguları. Evet, herhangi bir noktada parantezinizi tüm sorgunuza koyabilir ve bunu kaynak verileri ve hesaplanan alanları benzer şekilde işleyebileceğiniz bir alt sorgu olarak kullanabilirsiniz. Ama bunu ancak çok çirkin olmadan yapabilirsiniz. Çok çirkin.

  • Yinelenen kod. 3 uzun (CASE ... ELSE ... END) ifadenin en büyük değeri nedir? Bu okunabilir olacak!

    • Müşterilerinize lanet şeyleri kendileri hesaplamasını söyleyin.

Bir şey mi kaçırdım? Muhtemelen, bu yüzden yorum yapmaktan çekinmeyin. Ama hey, ÇAPRAZ UYGULAMA böyle durumlarda bir nimet gibi: sadece basit CROSS APPLY (select tbl.value + 1 as someFormula) as crossTblve voilà ekleyin ! Yeni alanınız artık kaynak verilerinizde her zaman olduğu gibi pratik olarak kullanıma hazırdır.

ÇAPRAZ UYGULAMA ile sunulan değerler ...

  • karışıma performans, karmaşıklık veya okunabilirlik sorunları eklemeden bir veya birden çok hesaplanan alan oluşturmak için kullanılabilir
  • JOIN'lerde olduğu gibi, sonraki birkaç CROSS APPLY ifadesi kendilerine başvurabilir: CROSS APPLY (select crossTbl.someFormula + 1 as someMoreFormula) as crossTbl2
  • sonraki JOIN koşullarında bir ÇAPRAZ UYGULAMA tarafından sunulan değerleri kullanabilirsiniz
  • Bonus olarak, Tablo değerli işlev yönü vardır

Dang, yapamayacakları bir şey yok!


1
Bu benden büyük bir +1, daha sık belirtilmediğinden şaşırdım. Belki de bu örneği, türetilmiş değerler zincirinde "prosedürel" hesaplamaları nasıl yapabileceğinizi gösterecek şekilde genişletebilirsiniz? Örneğin: ÇAPRAZ UYGULAMA (çarpı olarak crossTbl.value * tbl.multiplier'ı seçin) multiTbl - ÇAPRAZ UYGULAMA (multiTbl.Multiplied / tbl.DerivativeRatio'u Türetilmiş olarak seçin) türetilmişTbl - vb ...
mrmillsy

1
CASE..ELSE..END yerine Cross Apply'ın nasıl kullanılacağı hakkında daha fazla bilgi / örnek var mı?
przemo_li

3
@przemo_li UYGULA, başvurmak için bir vaka ifadesinin sonucunu (diğer şeylerin yanı sıra) saklamak için kullanılabilir. Bir yapı şöyle olabilir: subquery.intermediateResult> 0 OLARAK alt sorgu olarak bazı Tablo Dış Uygulamalarından SONA SEÇİN (ara: Sonuç olarak CASE ... END ... ELSE'i seçin).
mtone

14

Çapraz uygulama, bir XML alanıyla da iyi çalışır. Düğüm değerlerini diğer alanlarla birlikte seçmek isterseniz.

Örneğin, bazı xml içeren bir tablonuz varsa

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

Sorguyu kullanma

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

Sonuç döndürür

xt_id root_attribute_value node_attribute_value lt_name
----------------------------------------------------------------------
1     test1            1                    Benefits
1     test1            4                    FINRPTCOMPANY

13

Bu zaten teknik olarak çok iyi cevaplandı, ancak bunun nasıl son derece yararlı olduğuna dair somut bir örnek vereyim:

Diyelim ki iki tablonuz var, Müşteri ve Sipariş. Müşterilerin birçok siparişi var.

Bana müşteriler ve en son verdikleri sipariş hakkında ayrıntılar veren bir görünüm oluşturmak istiyorum. Sadece JOINS ile, bu hoş olmayan bazı birleşimler ve toplama gerektirir. Ancak Cross Apply ile süper kolay:

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

7

Çapraz uygulama, alt sorgunun bir sütununa ihtiyacınız olan alt sorguları değiştirmek için kullanılabilir

alt sorgu

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

burada şirket tablosunun sütunlarını seçemeyeceğim, böylece çapraz uygula

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

5

Sanırım okunabilirlik olmalı;)

ÇAPRAZ UYGULAMA, okuyan insanlar için soldaki tablodan her satıra uygulanacak bir UDF'nin kullanıldığını söylemek için biraz benzersiz olacaktır.

Tabii ki, bir ÇAPRAZ UYGULAMA'nın diğer arkadaşların yukarıda paylaştığı JOIN'dan daha iyi kullanıldığı başka sınırlamalar da vardır.


4

İşte performans farkı ve JOINS üzerinden kullanımı ile her şeyi açıklayan bir makale.

SQL Server ÇAPRAZ UYGULAMA VE DIŞ KATILAR üzerinden UYGULAMA

Bu makalede önerildiği gibi, normal birleştirme işlemleri (İÇ VE ÇAPRAZ) arasında performans farkı yoktur.

resim açıklamasını buraya girin

Kullanım farkı, aşağıdaki gibi bir sorgu yapmanız gerektiğinde gelir:

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)

Yani, işlevle ilişkilendirmeniz gerektiğinde. Bu, "Çok bölümlü tanımlayıcı" D.DepartmentID "bağlanamadı" hatasını verecek INNER JOIN kullanılarak yapılamaz . Burada, her satır okunduğunda değer işleve iletilir. Kulağa hoş geliyor. :)


3

Peki bu Inner Join karşı Cross Apply kullanmak için bir neden olarak uygun olup olmadığından emin değilim, ama bu sorgu Cross Apply kullanarak bir Forum Yazı benim için cevap verildi, bu yüzden Inner Join kullanarak bir eşdeğer yöntemi olup olmadığından emin değilim:

Create PROCEDURE [dbo].[Message_FindHighestMatches]

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

BAŞLANGIÇ OLARAK

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

SON


3

APPLY operatörünün özü, FROM yan tümcesinde operatörün sol ve sağ tarafı arasındaki korelasyona izin vermektir.

JOIN'in aksine, girdiler arasındaki korelasyona izin verilmez.

Uygula operatöründe korelasyon hakkında konuşmak gerekirse, sağ tarafa koyabileceğimiz anlamına gelir:

  • türetilmiş bir tablo - takma adla ilişkili bir alt sorgu olarak
  • tablo değerli fonksiyon - parametrenin sol tarafa bakabileceği parametrelerle kavramsal bir görünüm

Her ikisi de birden çok sütun ve satır döndürebilir.


2

Bu belki de eski bir soru, ama yine de mantığın yeniden kullanımını basitleştirmek ve sonuçlar için bir "zincirleme" mekanizması sağlamak için CROSS APPLY'un gücünü seviyorum.

Aşağıda, işler dağınık hale gelmeden veri kümenizde karmaşık mantıksal işlemler gerçekleştirmek için CROSS APPLY'yi nasıl kullanabileceğinizin basit bir örneğini gösteren bir SQL Fiddle sağladım. Buradan daha karmaşık hesaplamaları tahmin etmek zor değil.

http://sqlfiddle.com/#!3/23862/2


1

CROSS APPLY kullanan çoğu sorgu bir INNER JOIN kullanılarak yeniden yazılabilirken, CROSS APPLY daha iyi yürütme planı ve daha iyi performans sağlayabilir, çünkü birleştirme gerçekleşmeden önce birleştirilen seti sınırlayabilir.

Buradan Çalındı

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.