Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Quando devo usar CROSS APPLY sobre INNER JOIN?


Alguém pode me dar um bom exemplo de quando o CROSS APPLY faz a diferença nos casos em que o INNER JOIN também funcionará?

Veja o artigo no meu blog para uma comparação detalhada de desempenho:
  • INNER JOIN vs. CROSS APPLY

CROSS APPLY funciona melhor em coisas que não têm um simples JOIN doença.

Este seleciona 3 últimos registros de t2 para cada registro de 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

Não pode ser formulado facilmente com um INNER JOIN doença.

Você provavelmente poderia fazer algo assim usando CTE 's e função de janela:
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

, mas isso é menos legível e provavelmente menos eficiente.

Atualização:

Acabei de verificar.

master é uma tabela de aproximadamente 20,000,000 registros com uma PRIMARY KEY em id .

Esta consulta:
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

roda por quase 30 segundos, enquanto este:
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

é instantâneo.