Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Lorsque nous optons pour une application croisée et lorsque nous optons pour une jointure interne dans SQL Server 2012

INNER JOIN et CROSS APPLY (idem avec LEFT JOIN et OUTER APPLY ) sont très proches. Dans votre exemple, je suppose que le moteur trouvera le même plan d'exécution.

  • Un JOIN est un lien entre deux ensembles sur une condition
  • un APPLY est un ligne par ligne sous-appel

Mais - comme mentionné ci-dessus - l'optimiseur est très intelligent et comprendra - au moins dans des cas aussi simples - que cela revient au même.

  • Le JOIN essaiera de collecter le sous-ensemble et de le lier sur la condition spécifiée
  • Le APPLY essaiera d'appeler le résultat associé avec les valeurs de la ligne actuelle encore et encore.

Les différences résident dans l'appel de table-valued-functions (doit être inline -syntax !), avec la méthode XML .nodes() et avec des scénarios plus complexes.

Un exemple d'utilisation de APPLY pour simuler des variables

...pour utiliser le résultat d'un ligne par ligne calcul comme si vous utilisiez une variable :

DECLARE @dummy TABLE(ID INT IDENTITY, SomeString VARCHAR(100));
INSERT INTO @dummy VALUES('Want to split/this at the two/slashes.'),('And/this/also');

SELECT d.ID
      ,d.SomeString
      ,pos1
      ,pos2
      ,LEFT(d.SomeString,pos1-1)
      ,SUBSTRING(d.SomeString,pos1+1,pos2-pos1-1)
      ,SUBSTRING(d.SomeString,pos2+1,1000)
FROM @dummy AS d
CROSS APPLY(SELECT CHARINDEX('/',d.SomeString) AS pos1) AS x
CROSS APPLY(SELECT CHARINDEX('/',d.SomeString,x.pos1+1) AS pos2) AS y

C'est la même chose que ce qui suit, mais beaucoup plus facile à lire (et à taper) :

SELECT d.ID
      ,d.SomeString
      ,LEFT(d.SomeString,CHARINDEX('/',d.SomeString)-1)
      ,SUBSTRING(d.SomeString,CHARINDEX('/',d.SomeString)+1,CHARINDEX('/',d.SomeString,(CHARINDEX('/',d.SomeString)+1))-(CHARINDEX('/',d.SomeString)+1))
      ,SUBSTRING(d.SomeString,CHARINDEX('/',d.SomeString,(CHARINDEX('/',d.SomeString)+1))+1,1000)
FROM @dummy AS d

Un exemple avec la méthode XML .nodes()

DECLARE @dummy TABLE(SomeXML XML)
INSERT INTO @dummy VALUES
(N'<root>
  <a>a1</a>
  <a>a2</a>
  <a>a3</a>
  <b>Here is b!</b>
</root>');

SELECT All_a_nodes.value(N'.',N'nvarchar(max)')
FROM @dummy
CROSS APPLY SomeXML.nodes(N'/root/a') AS A(All_a_nodes);

Le résultat

a1
a2
a3

Et un exemple pour un appel de fonction en ligne

CREATE FUNCTION dbo.TestProduceRows(@i INT)
RETURNS TABLE
AS
RETURN
    SELECT TOP(@i) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nr FROM master..spt_values
GO

CREATE TABLE dbo.TestData(ID INT IDENTITY, SomeString VARCHAR(100),Number INT);
INSERT INTO dbo.TestData VALUES
 ('Show me once',1)
,('Show me twice',2)
,('Me five times!',5);

SELECT *
FROM TestData
CROSS APPLY dbo.TestProduceRows(Number) AS x;

GO
DROP TABLE dbo.TestData;
DROP FUNCTION dbo.TestProduceRows;

Le résultat

1   Show me once    1   1
2   Show me twice   2   1
2   Show me twice   2   2
3   Me five times!  5   1
3   Me five times!  5   2
3   Me five times!  5   3
3   Me five times!  5   4
3   Me five times!  5   5