Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Quando dovrei usare CROSS APPLY su INNER JOIN?

Qualcuno può darmi un buon esempio di quando CROSS APPLY fa la differenza nei casi in cui funzionerà anche INNER JOIN?

Vedi l'articolo nel mio blog per un confronto dettagliato delle prestazioni:

  • INNER JOIN rispetto a CROSS APPLY

CROSS APPLY funziona meglio su cose che non hanno un semplice JOIN condizione.

Questo seleziona 3 ultimi record da t2 per ogni record da 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

Non può essere formulato facilmente con un INNER JOIN condizione.

Probabilmente potresti fare qualcosa del genere usando CTE 's e funzione finestra:

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

, ma questo è meno leggibile e probabilmente meno efficiente.

Aggiornamento:

Ho appena controllato.

master è una tabella di circa 20,000,000 record con una PRIMARY KEY su id .

Questa domanda:

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

dura quasi 30 secondi, mentre questo:

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

è istantaneo.