GOOGLE ADS

dimanche 24 avril 2022

essayer d'obtenir la date maximale pour chaque identifiant avec des valeurs différentes en utilisant l'application croisée ou la jointure ?

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 :
entrez la description de l'image ici

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 :

entrez la description de l'image ici

Avec l'index en place, l' TOPapproche 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

Comment utiliseriez-vous .reduce() sur des arguments au lieu d'un tableau ou d'un objet spécifique ?

Je veux définir une fonction.flatten qui aplatit plusieurs éléments en un seul tableau. Je sais que ce qui suit n'est pas possible, mais...