J'ai entendu parler d'application croisée, mais à ce jour, je n'ai jamais pensé que j'avais besoin de l'utiliser. Vous trouverez ci-dessous un exemple de quelque chose que j'ai fait plusieurs fois, puis la même chose en utilisant une application croisée.
modifier * Quelqu'un peut-il expliquer quelle est la différence (le cas échéant) entre l'exemple de jointure et l'exemple d'application croisée pour cette situation
DROP TABLE IF EXISTS #test
/*creating test table and inserting test rows*/
create table #test (id char(1), val int, dt date)
insert into #test values ('a',1,'2022/1/6')
insert into #test values ('a',4,'2022/1/7')
insert into #test values ('a',7,'2022/1/8')
insert into #test values ('a',5,'2022/1/9')
insert into #test values ('a',3,'2022/1/10')
insert into #test values ('a',1,'2022/1/11')
insert into #test values ('b',1,'2022/1/6')
insert into #test values ('b',4,'2022/1/7')
insert into #test values ('b',6,'2022/1/8')
insert into #test values ('b',8,'2022/1/9')
insert into #test values ('b',3,'2022/1/10')
insert into #test values ('b',5,'2022/1/11')
insert into #test values ('c',1,'2022/1/6')
insert into #test values ('c',4,'2022/1/7')
insert into #test values ('c',6,'2022/1/8')
insert into #test values ('c',8,'2022/1/9')
insert into #test values ('c',3,'2022/1/10')
insert into #test values ('c',5,'2022/1/11')
-- this is the way I've been accomplishing this task
SELECT t.id
,t.val
,t.dt
FROM #test t
JOIN (
SELECT max(dt) max_dt
,id
FROM #test
GROUP BY id
) maxt ON maxt.max_dt = t.dt
AND maxt.id = t.id
ORDER BY t.id
--this gives the same results but using cross apply
select t1.*
from #test t1
cross apply
(
select max(t2.dt) dt, id
from #test t2 where t2.id = t1.id
group by id
) cx
where cx.dt = t1.dt
Solution du problème
Voici la façon dont je résoudrais ceci:
SELECT t.id, t.val, t.dt
FROM
(
SELECT t.*, RN = ROW_NUMBER() OVER (PARTITION BY t.ID ORDER BY t.dt DESC)
FROM #test AS t
) AS t
WHERE t.RN = 1;
La façon dont je détermine la méthode la plus efficace consiste à examiner le(s) plan(s) d'exécution. Comparons les plans d'exécution de deux méthodes que vous avez publiées et de la solution TOP que je viens de publier.
Plans d'exécution :
Dans ce cas, il n'y a aucune différence entre appliquer et la jointure interne que vous utilisez. Le bot retournera les mêmes données en utilisant des plans d'exécution identiques. Le coût des trois est égal (relativement). Dans ces plans, la majorité du travail se fera avec l'opérateur de tri requis pour déterminer la valeur MAX.
Ajoutons un index approprié pour cette requête :
CREATE NONCLUSTERED INDEX nc_test1 ON #test(id, dt DESC) INCLUDE(val);
Maintenant, réexécutons les trois requêtes :
Avec l'index en place, l' TOP
approche est la meilleure car elle ne nécessite pas d'auto-jointure et fait donc moins de la moitié du travail.
Aucun commentaire:
Enregistrer un commentaire