sql >> Database >  >> RDS >> Sqlserver

Wanneer we gaan voor cross apply en wanneer we gaan voor inner join in SQL Server 2012

INNER JOIN en CROSS APPLY (hetzelfde met LEFT JOIN en OUTER APPLY ) zijn zeer nauw verwant. In jouw voorbeeld zou ik aannemen dat de engine hetzelfde uitvoeringsplan zal vinden.

  • Een JOIN is een link tussen twee sets over een voorwaarde
  • een APPLY is een rijsgewijs suboproep

Maar - zoals hierboven vermeld - de optimizer is erg slim en zal - althans in zulke gemakkelijke gevallen - begrijpen dat het op hetzelfde neerkomt.

  • De JOIN zal proberen de subset te verzamelen en te koppelen boven de opgegeven voorwaarde
  • De APPLY zal proberen het gerelateerde resultaat met de waarden van de huidige rij aan te roepen keer op keer.

Verschillen zitten in het aanroepen van table-valued-functions (moet inline zijn -syntaxis!), met XML-methode .nodes() en met meer complexe scenario's.

Eén voorbeeld hoe men APPLY zou kunnen gebruiken om variabelen te simuleren

...om het resultaat van een rijsgewijs . te gebruiken berekening zoals u een variabele zou gebruiken:

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

Dit is hetzelfde als het volgende, maar veel gemakkelijker te lezen (en te typen):

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

Eén voorbeeld met XML-methode .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);

Het resultaat

a1
a2
a3

En een voorbeeld voor een inline-functieaanroep

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;

Het resultaat

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



  1. Eenvoudige recursieve query in Oracle

  2. Hoe retourneer ik 0 van een MySQL db wanneer de term in de Where-clausule niet in de database staat?

  3. Python-parsing van een SQL met behulp van pyparsing

  4. Hoe gebruik je een array met waarden uit PHP in de 'IN'-clausule van de mysql-query?