Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Kiedy decydujemy się na zastosowanie krzyżowe i kiedy decydujemy się na sprzężenie wewnętrzne w SQL Server 2012

INNER JOIN i CROSS APPLY (tak samo z LEFT JOIN i OUTER APPLY ) są bardzo blisko spokrewnione. W twoim przykładzie zakładam, że silnik znajdzie taki sam plan wykonania.

  • JOIN jest połączeniem między dwoma zestawami nad warunkiem
  • APPLY jest mądrym rzędem podrozmowa

Ale - jak wspomniano powyżej - optymalizator jest bardzo sprytny i - przynajmniej w tak łatwych przypadkach - zrozumie, że sprowadza się do tego samego.

  • JOIN spróbuje zebrać podzbiór i połączyć go powyżej określonego warunku
  • Karta APPLY spróbuje wywołać powiązany wynik z wartościami bieżącego wiersza w kółko.

Różnice dotyczą wywoływania funkcji o wartościach w tabeli (powinien być wbudowany -składnia!), z metodą XML .nodes() i z bardziej złożonymi scenariuszami.

Jeden przykład, jak można użyć APPLY symulować zmienne

...aby użyć wyniku wierszowego obliczenia tak, jakbyś używał zmiennej:

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

To jest to samo, co poniżej, ale o wiele łatwiejsze do odczytania (i wpisania):

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

Jeden przykład z metodą 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);

Wynik

a1
a2
a3

I jeden przykład wbudowanego wywołania funkcji

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;

Wynik

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Seminarium internetowe:Śledzenie postępu zapytań w SQL Server

  2. Dlaczego opcja indeksowania pełnotekstowego jest wyszarzona?

  3. Używanie SQL Server jako magazynu obrazów

  4. Połącz HP-UX Itanium z SQL Server

  5. Uzyskiwanie informacji o ograniczeniach domyślnych