<p>Quelqu’un peut-il me donner un bon exemple de cas où CROSS APPLY fait une différence dans les cas où INNER JOIN fonctionnerait aussi ?</p>
<p>Consultez l’article sur mon blog pour une comparaison détaillée des performances :</p>
<ul>
<li><a href="http://explainextended.com/2009/07/16/inner-join-vs-cross-apply/"><strong><code>INNER JOIN</code> vs. <code>CROSS APPLY</code></strong></a></li>
</ul>
<p><code>CROSS APPLY</code> fonctionne mieux sur les éléments qui n’ont pas de condition de <code>JOIN</code> simple.</p>
<p>Celui-ci sélectionne les <code>3</code> derniers enregistrements de <code>t2</code> pour chaque enregistrement de <code>t1</code> :</p>
<pre><code class="lang-auto">SELECT t1., t2o.
FROM t1
CROSS APPLY
(
SELECT TOP 3 *
FROM t2
WHERE t2.t1_id = t1.id
ORDER BY
t2.rank DESC
) t2o
</code></pre>
<p>Cela ne peut pas être facilement formulé avec une condition <code>INNER JOIN</code>.</p>
<p>Vous pourriez probablement faire quelque chose comme cela en utilisant des <code>CTE</code> et des fonctions de fenêtrage :</p>
<pre><code class="lang-auto">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
</code></pre>
<p>, mais c’est moins lisible et probablement moins efficace.</p>
<p><strong>Mise à jour :</strong></p>
<p>Vérification effectuée.</p>
<p><code>master</code> est une table d’environ <code>20 000 000</code> enregistrements avec une <code>PRIMARY KEY</code> sur <code>id</code>.</p>
<p>Cette requête :</p>
<pre><code class="lang-auto">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
</code></pre>
<p>s’exécute pendant presque <code>30</code> secondes, tandis que celle-ci :</p>
<pre><code class="lang-auto">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
</code></pre>
<p>est instantanée.</p>