Quand dois-je utiliser l'application croisée sur la jointure intérieure?

925

Quel est l'objectif principal de CROSS APPLY ?

J'ai lu (vaguement, à travers des publications sur Internet) qui cross applypeut être plus efficace lors de la sélection de plus grands ensembles de données si vous partitionnez. (La pagination vient à l'esprit)

Je sais également que CROSS APPLYcela ne nécessite pas un UDF comme table de droite.

Dans la plupart des INNER JOINrequêtes (relations un-à-plusieurs), je pouvais les réécrire pour les utiliser CROSS APPLY, mais elles me donnent toujours des plans d'exécution équivalents.

Quelqu'un peut-il me donner un bon exemple du moment où cela CROSS APPLYfait une différence dans les cas où INNER JOINcela fonctionnera également?


Éditer:

Voici un exemple trivial, où les plans d'exécution sont exactement les mêmes. (Montrez-moi celui où ils diffèrent et où cross applyest plus rapide / plus efficace)

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
la source
50
Je sais que c'est encore plus délicat de ma part, mais «performant» est certainement un mot. Ce n'est tout simplement pas lié à l'efficacité.
Rire1979
2
C'est très utile pour sql xquery. vérifiez cela .
ARZ
3
Il semble que l'utilisation de la "jointure de boucle interne" soit très proche d'une application croisée. Je souhaite que votre exemple soit détaillé et que l'indice de jointure était équivalent. Le simple fait de joindre peut entraîner une fusion interne / boucle / fusion ou même «autre» car il peut se réorganiser avec d'autres jointures.
crokusek
3
Lorsque la jointure créera un grand nombre de lignes, mais il vous suffit d'évaluer une jointure de ligne à la fois. J'avais un cas où j'avais besoin d'une auto-jointure sur une table avec plus de 100 millions de lignes et il n'y avait tout simplement pas assez de mémoire. Je suis donc allé curseur pour réduire l'empreinte mémoire. À partir du curseur, je suis passé à l'application croisée comme empreinte mémoire encore gérée et j'étais 1/3 plus rapide que le curseur.
paparazzo
10
CROSS APPLYa son utilisation évidente en permettant à un ensemble de dépendre d'un autre (contrairement à l' JOINopérateur), mais cela ne vient pas sans coût: il se comporte comme une fonction qui opère sur chaque membre de l' ensemble gauche , donc, en termes SQL Server, il effectuez toujours un Loop Join, ce qui n'est presque jamais le meilleur moyen de joindre des ensembles. Donc, utilisez-le APPLYquand vous en avez besoin, mais n'en abusez pas JOIN.
Gerardo Lima

Réponses:

668

Quelqu'un peut-il me donner un bon exemple de cas où CROSS APPLY fait une différence dans les cas où INNER JOIN fonctionnera également?

Voir l'article dans mon blog pour une comparaison détaillée des performances:

CROSS APPLYfonctionne mieux sur des choses qui n'ont pas de JOINcondition simple .

Celui-ci sélectionne les 3derniers enregistrements de t2pour chaque enregistrement parmi 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

Il ne peut pas être facilement formulé avec une INNER JOINcondition.

Vous pourriez probablement faire quelque chose comme ça en utilisant CTEla fonction s et window:

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

, mais c'est moins lisible et probablement moins efficace.

Mise à jour:

Je viens de vérifier.

masterest un tableau sur les 20,000,000enregistrements avec un PRIMARY KEYon id.

Cette requête:

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

fonctionne pendant près de 30secondes, tandis que celui-ci:

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

est instantané.

Quassnoi
la source
2
Voir la fin du lien d'Ariel. Une requête row_number () est tout aussi agréable et ne nécessite même pas de jointure. Je ne pense donc pas que je devrais utiliser l'application croisée pour cette situation (sélectionnez le top 3, partition par t1.id).
Jeff Meatball Yang
375
Bien que ce soit la réponse la plus populaire, je ne pense pas qu'elle réponde à la question réelle "Quel est le principal objectif de CROSS APPLY?". L'objectif principal est de permettre aux fonctions de table avec des paramètres d'être exécutées une fois par ligne, puis jointes aux résultats.
MikeKulls
5
@Mike: comment appeler un TVFavec INNER JOIN?
Quassnoi
15
@MikeKulls Oui, mais l'OP n'a pas demandé le but principal de l'utilisation CROSS APPLY, il a demandé quand le choisir INNER JOIN, quand cela fonctionnerait aussi.
ErikE
8
Il peut être utile de mentionner que cela s'appelle un lateral joinSQL standard (ANSI)
a_horse_with_no_name
198

cross apply vous permet parfois de faire des choses que vous ne pouvez pas faire avec inner join .

Exemple (une erreur de syntaxe):

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

Il s'agit d'une erreur de syntaxe , car, lorsqu'elle est utilisée avec inner join, les fonctions de table ne peuvent accepter que des variables ou des constantes comme paramètres. (C'est-à-dire que le paramètre de fonction de table ne peut pas dépendre de la colonne d'une autre table.)

Toutefois:

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

C'est légal.

Edit: Ou bien, une syntaxe plus courte: (par ErikE)

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

Éditer:

Remarque: Informix 12.10 xC2 + a des tableaux dérivés latéraux et Postgresql (9.3+) a des sous-requêtes latérales qui peuvent être utilisées pour un effet similaire.

nurettin
la source
11
Je pense que c'est le raisonnement derrière pourquoi nous avons la demande croisée. Si vous consultez le lien ci-dessous, c'est la première chose que MS dit à propos de l'application croisée. Il pourrait avoir d'autres utilisations, mais je pense que c'est la raison pour laquelle il a été introduit. Sans lui, les fonctions de table ne seraient pas utilisables dans de nombreuses situations. technet.microsoft.com/en-us/library/ms175156.aspx
MikeKulls
l'application croisée produit également un joli plan d'exécution lorsqu'elle est couplée à des fonctions de table en ligne tout en conservant la modularité indispensable.
nurettin
14
Pas SELECTbesoin à l'intérieur du CROSS APPLY. Veuillez essayer CROSS APPLY dbo.myTableFun(O.name) F.
ErikE
1
@ErikE bien sûr, vous pouvez toujours utiliser la syntaxe la moins flexible pour effectuer une application croisée. Je montrais la version plus généralisée que vous pouvez parfois utiliser afin d'éviter de placer des colonnes difficiles à calculer dans la requête.
nurettin
2
La jointure interne @Bolu ne fonctionnera pas si le paramètre de fonction de table dépend de la colonne d'une autre table (aka référence externe) dans la sélection externe. Cela fonctionnera si le paramètre de la fonction de table est un littéral ou une variable. L'application croisée fonctionnera dans les deux cas.
nurettin
175

Considérez que vous avez deux tables.

TABLE MAÎTRE

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

TABLEAU DE DÉTAILS

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

Il existe de nombreuses situations où nous devons remplacer INNER JOINavec CROSS APPLY.

1. Joignez deux tableaux en fonction des TOP nrésultats

Considérez si nous devons choisir Idet Namede Masteret deux dates pour chacun Idde 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

La requête ci-dessus génère le résultat suivant.

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

Voir, il a généré des résultats pour les deux dernières dates avec les deux dernières dates, Idpuis n'a joint ces enregistrements que dans la requête externe Id, ce qui est faux. Cela devrait renvoyer à la fois Ids1 et 2 mais il n'a renvoyé que 1 car 1 a les deux dernières dates. Pour ce faire, nous devons utiliser 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

et forme le résultat suivant.

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

Voici comment ça fonctionne. La requête à l'intérieur CROSS APPLYpeut référencer la table externe, où INNER JOINne peut pas le faire (elle génère une erreur de compilation). Lors de la recherche des deux dernières dates, la jonction se fait à l'intérieur, CROSS APPLYc'est- à- direWHERE M.ID=D.ID .

2. Lorsque nous avons besoin de INNER JOINfonctionnalités utilisant des fonctions.

CROSS APPLYpeut être utilisé en remplacement INNER JOINlorsque nous devons obtenir le résultat du Mastertableau et a function.

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

Et voici la fonction

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

qui a généré le résultat suivant

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

AVANTAGE SUPPLÉMENTAIRE DE L'APPLICATION CROISÉE

APPLYpeut être utilisé en remplacement de UNPIVOT. Soit CROSS APPLYou OUTER APPLYpeut être utilisé ici, qui sont interchangeables.

Considérez que vous avez le tableau ci-dessous (nommé 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

La requête est ci-dessous.

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

qui vous apporte le résultat

  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
la source
4
Excellent exemple avec les enregistrements 2 vs 4 et m'a aidé à comprendre le contexte dans lequel cela serait nécessaire.
trnelson
13
Cette réponse prouve qu'il vaut vraiment la peine de faire défiler la page au lieu de simplement choisir celle acceptée.
Mostafa Armandi du
2
Le meilleur exemple jusqu'ici pour expliquer l'utilisation de APPLY ... J'ai lu de nombreux articles et je me rends compte que cette explication efface l'image comme de l'eau. Merci beaucoup frère.
AG7
1
Pour le point 1 où nous avons 2 lignes pour l'ID 1 au lieu de 4 lignes pour l'ID 1, 2. Ne devrions-nous pas simplement utiliser une jointure gauche à la place.
Joseph Cho
43

Il me semble que CROSS APPLY peut combler une certaine lacune lorsque vous travaillez avec des champs calculés dans des requêtes complexes / imbriquées, et les rendre plus simples et plus lisibles.

Exemple simple: vous avez un DoB et vous souhaitez présenter plusieurs champs liés à l'âge qui s'appuieront également sur d'autres sources de données (telles que l'emploi), comme Age, AgeGroup, AgeAtHiring, MinimumRetirementDate, etc. pour une utilisation dans votre application d'utilisateur final (Excel PivotTables, par exemple).

Les options sont limitées et rarement élégantes:

  • Les sous-requêtes JOIN ne peuvent pas introduire de nouvelles valeurs dans l'ensemble de données sur la base des données de la requête parent (elles doivent être autonomes).

  • Les FDU sont soignés, mais lents car ils ont tendance à empêcher les opérations parallèles. Et être une entité distincte peut être une bonne chose (moins de code) ou une mauvaise chose (où est le code).

  • Tables de jonction. Parfois, ils peuvent fonctionner, mais assez tôt, vous rejoignez des sous-requêtes avec des tonnes d'UNIONS. Grand désordre.

  • Créez une autre vue à usage unique, en supposant que vos calculs ne nécessitent pas de données obtenues à mi-chemin de votre requête principale.

  • Tables intermédiaires. Oui ... cela fonctionne généralement, et souvent une bonne option car ils peuvent être indexés et rapides, mais les performances peuvent également baisser car les instructions UPDATE ne sont pas parallèles et ne permettent pas de mettre en cascade des formules (réutiliser les résultats) pour mettre à jour plusieurs champs dans le même déclaration. Et parfois, vous préférez simplement faire les choses en un seul passage.

  • Imbrication de requêtes. Oui, à tout moment, vous pouvez mettre des parenthèses sur l'ensemble de votre requête et l'utiliser comme sous-requête sur laquelle vous pouvez manipuler les données source et les champs calculés. Mais vous ne pouvez pas faire ça avant que ça ne devienne laid. Très laid.

  • Code répétitif. Quelle est la plus grande valeur de 3 instructions longues (CASE ... ELSE ... END)? Ça va être lisible!

    • Dites à vos clients de calculer eux-mêmes les fichues choses.

Ai-je oublié quelque chose? Probablement, alors n'hésitez pas à commenter. Mais bon, CROSS APPLY est comme une aubaine dans de telles situations: il suffit d'ajouter un simpleCROSS APPLY (select tbl.value + 1 as someFormula) as crossTbl et voilà! Votre nouveau champ est maintenant prêt à être utilisé pratiquement comme il l'avait toujours été dans vos données source.

Les valeurs introduites via CROSS APPLY peuvent ...

  • être utilisé pour créer un ou plusieurs champs calculés sans ajouter de problèmes de performances, de complexité ou de lisibilité au mélange
  • comme avec JOINs, plusieurs instructions CROSS APPLY ultérieures peuvent se référer à elles-mêmes: CROSS APPLY (select crossTbl.someFormula + 1 as someMoreFormula) as crossTbl2
  • vous pouvez utiliser les valeurs introduites par un CROSS APPLY dans les conditions JOIN ultérieures
  • En prime, il y a l'aspect fonction table

Dang, ils ne peuvent rien faire!

mtone
la source
1
C'est un gros +1 de ma part, car je suis surpris que ce ne soit pas mentionné plus souvent. Peut-être pourriez-vous étendre cet exemple pour montrer comment vous pouvez effectuer des calculs "procéduraux" sur la chaîne de valeurs dérivées? Par exemple: CROSS APPLY (sélectionner crossTbl.value * tbl.multiplier comme Multiplié) multiTbl - CROSS APPLY (sélectionner multiTbl.Multiplied / tbl.DerivativeRatio Dérivée) derivedTbl - etc ...
mrmillsy
1
D'autres informations / exemples sur la façon d'utiliser Cross Apply en remplacement de CASE..ELSE..END?
przemo_li
3
@przemo_li APPLY peut être utilisé pour stocker le résultat d'une instruction case (entre autres) afin de s'y référer. Une structure pourrait être quelque chose comme: SELECT CASE when subquery.intermediateResult> 0 THEN "yes" ELSE "no" END FROM someTable OUTER APPLY (sélectionnez CASE ... END ... ELSE as intermediaireResult) comme sous-requête.
mtone
14

L'application croisée fonctionne également bien avec un champ XML. Si vous souhaitez sélectionner des valeurs de nœud en combinaison avec d'autres champs.

Par exemple, si vous avez une table contenant du xml

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

Utilisation de la requête

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

Renvoie un résultat

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

Cela a déjà été très bien répondu techniquement, mais permettez-moi de donner un exemple concret de la façon dont il est extrêmement utile:

Disons que vous avez deux tables, Client et Commande. Les clients ont de nombreuses commandes.

Je veux créer une vue qui me donne des détails sur les clients et la dernière commande qu'ils ont passée. Avec juste JOINS, cela nécessiterait quelques auto-jointures et agrégation, ce qui n'est pas joli. Mais avec Cross Apply, c'est super simple:

SELECT *
FROM Customer
CROSS APPLY (
  SELECT TOP 1 *
  FROM Order
  WHERE Order.CustomerId = Customer.CustomerId
  ORDER BY OrderDate DESC
) T
Apnée
la source
7

L'application croisée peut être utilisée pour remplacer la sous-requête lorsque vous avez besoin d'une colonne de la sous-requête

sous-requête

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

ici, je ne pourrai pas sélectionner les colonnes du tableau de la société, donc, en utilisant l'application croisée

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
la source
5

Je suppose que ça devrait être la lisibilité;)

CROSS APPLY sera quelque peu unique pour les personnes qui lisent pour leur dire qu'un UDF est utilisé qui sera appliqué à chaque ligne du tableau de gauche.

Bien sûr, il existe d'autres limitations lorsqu'un CROSS APPLY est mieux utilisé que JOIN que d'autres amis ont posté ci-dessus.

shahkalpesh
la source
4

Voici un article qui explique tout, avec leur différence de performances et leur utilisation sur JOINS.

SQL Server CROSS APPLY et OUTER APPLY over JOINS

Comme suggéré dans cet article, il n'y a aucune différence de performances entre eux pour les opérations de jointure normales (INNER ET CROSS).

entrez la description de l'image ici

La différence d'utilisation survient lorsque vous devez effectuer une requête comme celle-ci:

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)

Autrement dit, lorsque vous devez vous rapporter à la fonction. Cela ne peut pas être fait en utilisant INNER JOIN, ce qui vous donnerait l'erreur "L'identifiant en plusieurs parties" D.DepartmentID "n'a pas pu être lié." Ici, la valeur est transmise à la fonction lors de la lecture de chaque ligne. Ça me semble cool. :)

Shanid
la source
3

Eh bien, je ne sais pas si cela peut être considéré comme une raison d'utiliser l'application croisée par opposition à la jointure interne, mais cette question a été répondue pour moi dans un message sur le forum à l'aide de l'application croisée, donc je ne suis pas sûr s'il existe une méthode équivalente utilisant la jointure interne:

Create PROCEDURE [dbo].[Message_FindHighestMatches]

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

COMME COMMENCER

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

FIN

user1054326
la source
3

L'essence de l'opérateur APPLY est de permettre la corrélation entre le côté gauche et le côté droit de l'opérateur dans la clause FROM.

Contrairement à JOIN, la corrélation entre les entrées n'est pas autorisée.

En parlant de corrélation dans l'opérateur APPLY, je veux dire sur le côté droit, nous pouvons mettre:

  • une table dérivée - en tant que sous-requête corrélée avec un alias
  • une fonction table - une vue conceptuelle avec des paramètres, où le paramètre peut faire référence au côté gauche

Les deux peuvent renvoyer plusieurs colonnes et lignes.

Raf
la source
2

C'est peut-être une vieille question, mais j'aime toujours la puissance de CROSS APPLY pour simplifier la réutilisation de la logique et pour fournir un mécanisme de "chaînage" des résultats.

J'ai fourni un SQL Fiddle ci-dessous qui montre un exemple simple de la façon dont vous pouvez utiliser CROSS APPLY pour effectuer des opérations logiques complexes sur votre ensemble de données sans que les choses deviennent du tout compliquées. Il n'est pas difficile d'extrapoler à partir d'ici des calculs plus complexes.

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

mrmillsy
la source
1

Alors que la plupart des requêtes qui utilisent CROSS APPLY peuvent être réécrites à l'aide d'un INNER JOIN, CROSS APPLY peut fournir un meilleur plan d'exécution et de meilleures performances, car il peut limiter l'ensemble à joindre avant que la jointure ne se produise.

Volé d' ici

Greg Gum
la source