Wann sollte ich cross apply over inner join verwenden?


925

Was ist der Hauptzweck von CROSS APPLY ?

Ich habe (vage durch Beiträge im Internet) gelesen, dass cross applyes effizienter sein kann, wenn Sie über große Datenmengen auswählen, wenn Sie partitionieren. (Paging kommt mir in den Sinn)

Ich weiß auch, dass CROSS APPLYkeine UDF als richtige Tabelle erforderlich ist.

In den meisten INNER JOINAbfragen (Eins-zu-Viele-Beziehungen) konnte ich sie zur Verwendung umschreiben CROSS APPLY, aber sie geben mir immer gleichwertige Ausführungspläne.

Kann mir jemand ein gutes Beispiel geben, wann CROSS APPLYes in den Fällen, in denen INNER JOINes auch funktioniert, einen Unterschied macht ?


Bearbeiten:

Hier ist ein einfaches Beispiel, bei dem die Ausführungspläne genau gleich sind. (Zeigen Sie mir, wo sie sich unterscheiden und wo sie cross applyschneller / effizienter sind)

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
Ich weiß, das ist NOCH PICKIER von mir, aber 'performant' ist definitiv ein Wort. Es hängt einfach nicht mit der Effizienz zusammen.
Rire1979

2
Es ist sehr nützlich für SQL XQuery. Überprüfen Sie dies .
ARZ

3
Es scheint, als würde die Verwendung von "Inner Loop Join" sehr nahe an der Kreuzanwendung liegen. Ich wünsche mir ein detailliertes Beispiel, welcher Join-Hinweis gleichwertig ist. Wenn Sie nur Join sagen, kann dies zu inner / loop / merge oder sogar zu "other" führen, da dies möglicherweise mit anderen Joins neu arrangiert wird.
Crokusek

3
Wenn der Join viele Zeilen erstellt, Sie jedoch jeweils nur einen Zeilen-Join auswerten müssen. Ich hatte einen Fall, in dem ich einen Self-Join für eine Tabelle mit über 100 Millionen Zeilen benötigte und einfach nicht genügend Speicher vorhanden war. Also habe ich den Cursor gedrückt, um den Speicherbedarf zu verringern. Vom Cursor ging ich als noch verwalteter Speicherbedarf über Kreuz anwenden und war 1/3 schneller als der Cursor.
Paparazzo

10
CROSS APPLYhat seine offensichtliche Verwendung darin, zuzulassen, dass ein Satz von einem anderen abhängt (im Gegensatz zum JOINOperator), aber das ist nicht ohne Kosten: Es verhält sich wie eine Funktion, die über jedes Mitglied des linken Satzes ausgeführt wird, also in SQL Server-Begriffen Führen Sie immer eine aus Loop Join, was fast nie der beste Weg ist, um Sets zu verbinden. Verwenden APPLYSie es also, wenn Sie es brauchen, aber verwenden Sie es nicht zu stark JOIN.
Gerardo Lima

Antworten:


667

Kann mir jemand ein gutes Beispiel geben, wann CROSS APPLY in den Fällen, in denen INNER JOIN ebenfalls funktioniert, einen Unterschied macht?

Im Artikel in meinem Blog finden Sie einen detaillierten Leistungsvergleich:

CROSS APPLYfunktioniert besser bei Dingen, die keinen einfachen JOINZustand haben.

Dieser wählt die 3letzten Datensätze aus t2für jeden Datensatz aus 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

Es kann nicht einfach mit einer INNER JOINBedingung formuliert werden.

Sie könnten wahrscheinlich so etwas mit CTEder Funktion 's' und 'window' machen:

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

, aber das ist weniger lesbar und wahrscheinlich weniger effizient.

Aktualisieren:

Gerade nachgeguckt.

masterist eine Tabelle von etwa 20,000,000Aufzeichnungen mit einem PRIMARY KEYauf id.

Diese Abfrage:

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

läuft fast 30Sekunden, während dieser:

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

ist sofort.


2
Siehe das Ende von Ariels Link. Eine row_number () - Abfrage ist genauso schön und erfordert nicht einmal einen Join. Daher denke ich nicht, dass ich für diese Situation cross apply verwenden sollte (wählen Sie Top 3, Partition von t1.id).
Jeff Meatball Yang

375
Obwohl dies die beliebteste Antwort ist, glaube ich nicht, dass sie die eigentliche Frage "Was ist der Hauptzweck der Verwendung von CROSS APPLY?" Beantwortet. Der Hauptzweck besteht darin, Tabellenfunktionen mit Parametern zu aktivieren, die einmal pro Zeile ausgeführt und dann mit den Ergebnissen verknüpft werden.
MikeKulls

5
@ Mike: Wie rufst du ein TVFmit an INNER JOIN?
Quassnoi

15
@MikeKulls Ja, aber das OP hat nicht nach dem Hauptzweck der Verwendung CROSS APPLYgefragt , sondern nach dem Zeitpunkt der Auswahl INNER JOIN, wann dies auch funktionieren würde.
ErikE

8
Es könnte erwähnenswert sein, dass dies a genannt wird lateral join in Standard (ANSI) SQL bezeichnet wird
a_horse_with_no_name

198

cross applyManchmal können Sie Dinge tun, mit denen Sie nichts anfangen können inner join.

Beispiel (ein Syntaxfehler):

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

Dies ist ein Syntaxfehler , da inner joinTabellenfunktionen bei Verwendung mit nur Variablen oder Konstanten als Parameter verwenden können. (Das heißt, der Tabellenfunktionsparameter kann nicht von der Spalte einer anderen Tabelle abhängen.)

Jedoch:

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

Das ist legal.

Edit: Oder alternativ kürzere Syntax: (von ErikE)

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

Bearbeiten:

Hinweis: Informix 12.10 xC2 + verfügt über seitlich abgeleitete Tabellen und Postgresql (9.3+) über seitliche Unterabfragen , die auf ähnliche Weise verwendet werden können.


11
Ich denke, dies ist der Grund, warum wir uns gegenseitig bewerben. Wenn Sie sich den Link unten ansehen, ist dies das erste, was MS über Cross Apply sagt. Es könnte andere Verwendungszwecke haben, aber ich denke, dies ist der Grund, warum es eingeführt wurde. Ohne sie wären Tabellenfunktionen in vielen Situationen nicht verwendbar. technet.microsoft.com/en-us/library/ms175156.aspx
MikeKulls

cross apply erzeugt auch einen schönen Ausführungsplan, wenn es mit Inline-Tabellenfunktionen gekoppelt wird, während die dringend benötigte Modularität beibehalten wird.
Nurettin

14
Nicht SELECTbenötigt in der CROSS APPLY. Bitte versuchen Sie es CROSS APPLY dbo.myTableFun(O.name) F.
ErikE

1
@ErikE sicher, Sie können immer die weniger flexible Syntax verwenden, um Cross-Apply. Ich habe die allgemeinere Version gezeigt, die Sie manchmal verwenden können, um zu vermeiden, dass schwer zu berechnende Spalten in die Abfrage aufgenommen werden.
Nurettin

2
@Bolu inner join funktioniert nicht, wenn der Tabellenfunktionsparameter von der Spalte einer anderen Tabelle (auch als externe Referenz bezeichnet) in der externen Auswahl abhängt. Dies funktioniert, wenn der Tabellenfunktionsparameter ein Literal oder eine Variable ist. Cross Apply funktioniert in beiden Fällen.
Nurettin

175

Angenommen, Sie haben zwei Tabellen.

MASTER TABLE

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

DETAILS TABELLE

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

Es gibt viele Situationen , in denen wir ersetzen müssen INNER JOINmit CROSS APPLY.

1. Verbinden Sie zwei Tabellen basierend auf den TOP nErgebnissen

Überlegen Sie, ob wir müssen wählen Idund Nameaus Masterund die letzten beiden Tage , für jeden Idaus 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

Die obige Abfrage generiert das folgende Ergebnis.

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

Es wurden Ergebnisse für die letzten beiden Daten mit den letzten beiden Daten generiert Idund diese Datensätze dann nur in der äußeren Abfrage am verknüpft Id, was falsch ist. Dies sollte sowohl Ids1 als auch 2 zurückgeben, aber es wird nur 1 zurückgegeben, da 1 die letzten beiden Daten hat. Um dies zu erreichen, müssen wir verwenden 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

und bildet das folgende Ergebnis.

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

So funktioniert das. Die Abfrage im Inneren CROSS APPLYkann auf die äußere Tabelle verweisen, wo INNER JOINdies nicht möglich ist (es wird ein Kompilierungsfehler ausgelöst). Wenn die letzten zwei Tage , zu finden, erfolgt das Fügen im Inneren getan CROSS APPLYdh WHERE M.ID=D.ID.

2. Wenn wir INNER JOINFunktionalität mit Funktionen benötigen .

CROSS APPLYkann als Ersatz verwendet werden, INNER JOINwenn wir Ergebnisse aus MasterTabelle und a erhalten müssen function.

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

Und hier ist die Funktion

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

welches das folgende Ergebnis erzeugte

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

ZUSÄTZLICHER VORTEIL DER KREUZANWENDUNG

APPLYkann als Ersatz für verwendet werden UNPIVOT. Entweder CROSS APPLYoderOUTER APPLY kann hier verwendet werden, die austauschbar sind.

Angenommen, Sie haben die folgende Tabelle (benannt 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

Die Abfrage ist unten.

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

das bringt dir das Ergebnis

  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
Hervorragendes Beispiel mit den 2 vs 4 Datensätzen und hat mir geholfen, den Kontext zu verstehen, in dem dies erforderlich wäre.
Trnelson

13
Diese Antwort zeigt, dass es sich wirklich lohnt, die Seite nach unten zu scrollen, anstatt nur die akzeptierte auszuwählen.
Mostafa Armandi

2
Das bisher beste Beispiel, um die Verwendung von APPLY zu erklären ... Ich habe viele Beiträge gelesen und festgestellt, dass diese Erklärung das Bild als Wasser verdeutlicht. Vielen Dank, Bruder.
AG7

1
Für Punkt 1, wo wir 2 Zeilen für ID 1 anstelle von 4 Zeilen für ID 1, 2 haben. Würden wir nicht stattdessen einfach einen linken Join verwenden?
Joseph Cho

43

Es scheint mir, dass CROSS APPLY eine bestimmte Lücke füllen kann, wenn mit berechneten Feldern in komplexen / verschachtelten Abfragen gearbeitet wird, und diese einfacher und lesbarer machen kann.

Einfaches Beispiel: Sie haben ein DoB und möchten mehrere altersbezogene Felder anzeigen, die auch auf anderen Datenquellen (z. B. Beschäftigung) wie Age, AgeGroup, AgeAtHiring, MinimumRetirementDate usw. zur Verwendung in Ihrer Endbenutzeranwendung basieren (Zum Beispiel Excel PivotTables).

Die Möglichkeiten sind begrenzt und selten elegant:

  • JOIN-Unterabfragen können keine neuen Werte in das Dataset einführen, die auf Daten in der übergeordneten Abfrage basieren (sie müssen für sich allein stehen).

  • UDFs sind ordentlich, aber langsam, da sie dazu neigen, parallele Operationen zu verhindern. Und eine separate Einheit zu sein, kann eine gute (weniger Code) oder eine schlechte (wo ist der Code) Sache sein.

  • Verbindungstabellen. Manchmal können sie funktionieren, aber schon bald schließen Sie sich Unterabfragen mit Tonnen von UNIONs an. Großes Chaos.

  • Erstellen Sie eine weitere Einzelansicht, vorausgesetzt, Ihre Berechnungen erfordern keine Daten, die in der Mitte Ihrer Hauptabfrage abgerufen wurden.

  • Zwischentabellen. Ja ... das funktioniert normalerweise und ist oft eine gute Option, da sie indiziert und schnell sind. Die Leistung kann jedoch auch sinken, weil UPDATE-Anweisungen nicht parallel sind und es nicht möglich ist, Formeln zu kaskadieren (Ergebnisse wiederzuverwenden), um mehrere Felder innerhalb der zu aktualisieren gleiche Aussage. Und manchmal möchten Sie es einfach vorziehen, Dinge in einem Durchgang zu erledigen.

  • Verschachtelungsabfragen. Ja, Sie können Ihre gesamte Abfrage jederzeit in Klammern setzen und als Unterabfrage verwenden, mit der Sie Quelldaten und berechnete Felder gleichermaßen bearbeiten können. Aber Sie können dies nur so oft tun, bevor es hässlich wird. Sehr hässlich.

  • Code wiederholen. Was ist der größte Wert von 3 langen Anweisungen (CASE ... ELSE ... END)? Das wird lesbar sein!

    • Sagen Sie Ihren Kunden, sie sollen die verdammten Dinge selbst berechnen.

Habe ich etwas verpasst? Wahrscheinlich, also zögern Sie nicht zu kommentieren. Aber hey, CROSS APPLY ist in solchen Situationen wie ein Glücksfall: Sie fügen einfach ein einfaches hinzuCROSS APPLY (select tbl.value + 1 as someFormula) as crossTbl und voilà hinzu! Ihr neues Feld ist jetzt praktisch einsatzbereit, so wie es in Ihren Quelldaten immer vorhanden war.

Durch CROSS APPLY eingeführte Werte können ...

  • kann verwendet werden, um ein oder mehrere berechnete Felder zu erstellen, ohne dem Mix Leistungs-, Komplexitäts- oder Lesbarkeitsprobleme hinzuzufügen
  • Wie bei JOINs können sich mehrere nachfolgende CROSS APPLY-Anweisungen auf sich selbst beziehen: CROSS APPLY (select crossTbl.someFormula + 1 as someMoreFormula) as crossTbl2
  • Sie können Werte verwenden, die von CROSS APPLY in nachfolgenden JOIN-Bedingungen eingegeben wurden
  • Als Bonus gibt es den Tabellenaspekt-Funktionsaspekt

Verdammt, es gibt nichts, was sie nicht können!


1
Dies ist eine große +1 von mir, da ich überrascht bin, dass sie nicht öfter erwähnt wird. Vielleicht könnten Sie dieses Beispiel erweitern, um zu zeigen, wie Sie "prozedurale" Berechnungen für die Kette abgeleiteter Werte durchführen können? Beispiel: CROSS APPLY (wählen Sie crossTbl.value * tbl.multiplier als Multipliziert aus) multiTbl - CROSS APPLY (wählen Sie multiTbl.Multiplied / tbl.DerivativeRatio as Derived) abgeleitetTbl - etc ...
mrmillsy

1
Weitere Informationen / Beispiele zur Verwendung von Cross Apply als Ersatz für CASE..ELSE..END?
przemo_li

3
@przemo_li APPLY kann verwendet werden, um das Ergebnis einer case-Anweisung (unter anderem) zu speichern, um darauf zu verweisen. Eine Struktur könnte ungefähr so ​​aussehen: SELECT CASE when subquery.intermediateResult> 0 THEN "yes" ELSE "no" END FROM someTable OUTER APPLY (wählen Sie CASE ... END ... ELSE als intermediäres Ergebnis) als Unterabfrage.
mtone

14

Cross Apply funktioniert auch gut mit einem XML-Feld. Wenn Sie Knotenwerte in Kombination mit anderen Feldern auswählen möchten.

Zum Beispiel, wenn Sie eine Tabelle mit XML haben

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

Verwenden der Abfrage

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

Gibt ein Ergebnis zurück

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

13

Dies wurde technisch bereits sehr gut beantwortet, aber lassen Sie mich ein konkretes Beispiel dafür geben, wie äußerst nützlich es ist:

Nehmen wir an, Sie haben zwei Tabellen: Kunde und Bestellung. Kunden haben viele Bestellungen.

Ich möchte eine Ansicht erstellen, die Details zu Kunden und der letzten Bestellung enthält, die sie getätigt haben. Mit nur JOINS würde dies einige Self-Joins und Aggregationen erfordern, was nicht schön ist. Aber mit Cross Apply ist es super einfach:

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

7

Cross Apply kann verwendet werden, um Unterabfragen zu ersetzen, bei denen Sie eine Spalte der Unterabfrage benötigen

Unterabfrage

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

Hier kann ich die Spalten der Firmentabelle nicht mit cross apply auswählen

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

Ich denke es sollte Lesbarkeit sein;)

CROSS APPLY ist für Leser etwas Einzigartiges, um ihnen mitzuteilen, dass eine UDF verwendet wird, die auf jede Zeile aus der Tabelle links angewendet wird.

Natürlich gibt es andere Einschränkungen, bei denen eine CROSS APPLY besser verwendet wird als JOIN, die andere Freunde oben gepostet haben.


4

Hier ist ein Artikel, der alles erklärt, mit dem Leistungsunterschied und der Verwendung über JOINS.

SQL Server CROSS APPLY und OUTER APPLY über JOINS

Wie in diesem Artikel vorgeschlagen, gibt es keinen Leistungsunterschied zwischen ihnen für normale Verknüpfungsvorgänge (INNER AND CROSS).

Geben Sie hier die Bildbeschreibung ein

Der Nutzungsunterschied tritt auf, wenn Sie eine Abfrage wie folgt ausführen müssen:

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)

Das heißt, wenn Sie sich auf die Funktion beziehen müssen. Dies kann nicht mit INNER JOIN durchgeführt werden, was den Fehler "Die mehrteilige Kennung" D.DepartmentID "konnte nicht gebunden werden." Hier wird der Wert beim Lesen jeder Zeile an die Funktion übergeben. Klingt cool für mich. :) :)


3

Ich bin mir nicht sicher, ob dies ein Grund für die Verwendung von Cross Apply im Vergleich zu Inner Join ist, aber diese Abfrage wurde für mich in einem Forumbeitrag mit Cross Apply beantwortet. Daher bin ich mir nicht sicher, ob es eine gleichwertige Methode mit Inner Join gibt:

Create PROCEDURE [dbo].[Message_FindHighestMatches]

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

WIE BEGINNEN

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

ENDE


3

Der APPLY-Operator besteht im Wesentlichen darin, eine Korrelation zwischen der linken und der rechten Seite des Operators in der FROM-Klausel zuzulassen.

Im Gegensatz zu JOIN ist die Korrelation zwischen Eingaben nicht zulässig.

Wenn ich über die Korrelation im APPLY-Operator spreche, meine ich auf der rechten Seite, die wir setzen können:

  • eine abgeleitete Tabelle - als korrelierte Unterabfrage mit einem Alias
  • eine Tabellenwertfunktion - eine konzeptionelle Ansicht mit Parametern, wobei sich der Parameter auf die linke Seite beziehen kann

Beide können mehrere Spalten und Zeilen zurückgeben.


2

Dies ist vielleicht eine alte Frage, aber ich liebe immer noch die Fähigkeit von CROSS APPLY, die Wiederverwendung von Logik zu vereinfachen und einen "Verkettungs" -Mechanismus für Ergebnisse bereitzustellen.

Im Folgenden habe ich eine SQL-Geige bereitgestellt, die ein einfaches Beispiel dafür zeigt, wie Sie mit CROSS APPLY komplexe logische Operationen an Ihrem Datensatz ausführen können, ohne dass die Dinge chaotisch werden. Es ist nicht schwer, hier komplexere Berechnungen zu extrapolieren.

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


1

Während die meisten Abfragen, die CROSS APPLY verwenden, mit einem INNER JOIN neu geschrieben werden können, kann CROSS APPLY einen besseren Ausführungsplan und eine bessere Leistung liefern, da dies die Verknüpfung der Gruppe noch vor dem Join einschränken kann.

Von hier gestohlen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.