0
votes

SQL Effectuer AVG après Max

J'ai deux tables. Table1 CODE>:

SELECT t1.ID1, t1.ID2, t1.ID3, t1.ID4, maxDate, avgCost
FROM Table1 t1
JOIN ( SELECT ID1, ID2, ID3, ID4, MAX(Date) as maxDate, AVG(Cost) as avgCost
FROM Table2 t2
GROUP BY ID1, ID2, ID3, ID4 ) t2
ON t2.ID1 = t1.ID1
AND t2.ID2 = t1.ID2
AND t2.ID3 = t1.ID3
AND t2.ID4 = t1.ID4
WHERE maxDate = (SELECT MAX(Date) from Table2 GROUP BY ID1, ID2, ID3, ID4);


8 commentaires

Dans votre exemple de données, il n'y a pas les valeurs T1.ID4. Pourquoi ???


@scAISEDGE Désolé, corrigé


Basé sur l'échantillon de données de votre tableau 2, vous ne pouvez pas obtenir deux lignes .. Êtes-vous sûr que les données sont identiques et il n'y a pas de caractère caché .. qui renvoie 2 rangées agrégées


@SCAISEZ OKY, donc j'ai simplifié les comparaisons étant faites un peu. Le 4ème identifiant est en fait une chaîne et la comparaison est substr (t1.id4, 1, 5) = substr (t2.id4, 1, 5) . Il est vrai que, où coûte est 0.00 dans table2 , il y a 6 caractères dans ID4 pendant que le reste n'a que le reste 5. Mais cela ne devrait-il pas être réconcilié avec le substrateur (t2.id4, 1, 5) ?


Et vous devriez avoir 0.2 et avgcost résultat.


@ Barbarosözhan regarde mon explication. Une partie du problème est que chaque fois que coût est 0.00 dans table2 , il n'est pas compté dans le avg (coût) fonction. Je suis retourné deux rangées quand il ne devrait y avoir qu'un


Je l'ai déjà regardé votre explication, mais vous devriez déjà besoin d'avoir un row.Consider: dbfiddle.uk / ...


@ Barbarosözhan d'accord, j'avais réellement réparé ça. Si vous voyez les commentaires ci-dessus, ID4 est en fait une chaîne et je devais comparer les 5 premiers caractères de cette chaîne. J'ai corrigé le problème en modifiant mon Groupe par à Groupe par ID1, ID2, ID3, SUBSTR (ID4, 1, 5) . Merci!


3 Réponses :


0
votes

Essayez ceci, pourrait ne pas être la solution optimale, mais vous pouvez la juquer la meilleure performance

WITH MAXDATE AS (
SELECT  MAX(DATE) AS MAXDATE,
        ID1,
        ID2,
        ID3,
        ID4
FROM TABLE2
GROUP BY ID1,ID2,ID3,ID4
)
SELECT ID1, ID2, ID3, ID4, MAX(DATE), AVG(COST)
FROM TABLE1 T1 JOIN TABLE2 T2
ON T1.ID1 = T2.ID1
ON T1.ID2 = T2.ID2
ON T1.ID3 = T2.ID3
ON T1.ID4 = T2.ID4 JOIN MAXDATE T3
ON T1.ID1 = T3.ID1
ON T1.ID2 = T3.ID2
ON T1.ID3 = T3.ID3
ON T1.ID4 = T3.ID4
ON T2.DATE = T3.MAXDATE

GROUP BY T1.ID1
         T1.ID2
         T1.ID3
         T1.ID4


0 commentaires

-1
votes

Vous semblez vouloir:

select id1, id2, id3, id4, date, avg(cost)
from (select t2.*,
             dense_rank() over (partition by id1, id2, id3, id4 order by date desc) as seqnum
      from table2 t2
      where (id1, id2, id3, id4) in (select id1, id2, id3, id4 from table1)
     ) t2
where seqnum = 1
group by id1, id2, id3, id4, date;


2 commentaires

Oui, cela le résout. Regardé par-dessus certaines informations pour dense_rank () et partition par et il semble avoir un sens. Pourriez-vous expliquer ce que le où seqnum = 1 fait?


-1 De moi pour utiliser une fonction analytique où ce n'est pas nécessaire. La solution correcte consiste à utiliser la fonction d'agrégat Dernière - La requête devient beaucoup plus efficace.



2
votes

Votre définition de t2 ressemble à ceci: xxx

à la place, pour calculer la moyenne uniquement sur la date la plus récente devrait utiliser une fonction d'agrégat différente différente - la fonction Dernière , comme: xxx


0 commentaires