sql >> Databasteknik >  >> RDS >> Sqlserver

När vi går för kors ansöker vi och när vi går för inre join i SQL Server 2012

INRE JOIN och KORSA APPLY (samma med LEFT JOIN och YTTRE APPLY ) är mycket nära besläktade. I ditt exempel skulle jag anta att motorn kommer att hitta samma utförandeplan.

  • En JOIN är en länk mellan två uppsättningar över ett villkor
  • en APPLY är en radvis underanrop

Men - som nämnts ovan - optimeraren är väldigt smart och kommer - åtminstone i så lätta fall - att förstå att det handlar om samma sak.

  • JOIN kommer att försöka samla in underuppsättningen och länka den över det angivna villkoret
  • APPLY kommer att försöka ropa upp det relaterade resultatet med den aktuella radens värden om och om igen.

Det finns skillnader i att anropa tabellvärderade-funktioner (bör vara inline -syntax!), med XML-metoden .nodes() och med mer komplexa scenarier.

Ett exempel på hur man kan använda APPLY för att simulera variabler

...för att använda resultatet av en radvis beräkning som om du skulle använda en variabel:

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

Detta är samma som följande, men mycket lättare att läsa (och skriva):

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

Ett exempel med XML-metoden .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);

Resultatet

a1
a2
a3

Och ett exempel på ett infogat funktionsanrop

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;

Resultatet

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. Mysql välj för uppdatering - det låser inte målraderna. Hur ser jag till att det gör det?

  2. Ansluta en 64-bitars applikation till Clarion TopSpeed

  3. PostgreSQL:Vad är det maximala antalet tabeller som kan lagras i postgreSQL-databasen?

  4. Hur man installerar MariaDB-databasen i Debian 10