Je voulais obtenir le nombre consécutif d'enregistrements dont une certaine valeur de champ est périmée en fonction du tableau des taux. À partir des enregistrements de données ci-dessous, 3,4,5 ont le même taux que 0,770827, donc le nombre de jours où le taux est périmé est de 3 et le taux précédent avant périmé est de 0,770886.Je voudrais obtenir de l'aide pour écrire une requête au no d'enregistrements qui ont un taux périmé et obtiennent également le taux antérieur du même. Dans l'exemple ci-dessous, je montre uniquement le CAD en USD, mais nous avons besoin du même taux dans différentes devises. Toute assistance serait très utile.
Résultat attendu
3 Réponses :
Il s'agit d'un problème de lacunes et d'îles.
Vous pouvez utiliser lag ()
pour récupérer le rate
précédent pour le même tuple de devises, puis faire une fenêtre sum pour définir des groupes d'enregistrements consécutifs avec le même taux. Ensuite, vous pouvez agréger les groupes et récupérer le taux précédent en utilisant à nouveau lag ()
. La dernière étape consiste à filtrer sur les groupes qui ont au moins 3 enregistrements.
select * from ( select from_cur, to_cur, rate, max(date) max_date, lag(rate) over(partition by from_cur, to_cur order by max(date)) lag_rate_grp, count(*) cnt, row_number() over(partition by from_cur, to_cur, case when count(*) >= 3 then 0 else 1 end order by max(date)) rn from ( select t.*, row_number() over(partition by from_cur, to_cur order by date) rn1, row_number() over(partition by from_cur, to_cur, rate order by date) rn2 from mytable t ) t group by from_cur, to_cur, rate, rn1 - rn2 ) t where cnt >= 3 and rn = 1 order by from_cur, to_cur
En fait, l'utilisation de la différence entre les numéros de ligne peut économiser un niveau d'imbrication:
XXX
Si vous ne voulez que l'enregistrement le plus ancien par tuple de devise, vous pouvez utiliser row_number()
:
select * from ( select from_cur, to_cur, rate, max(date) max_date, lag(rate) over(partition by from_cur, to_cur order by max(date)) lag_rate_grp, count(*) cnt from ( select t.*, row_number() over(partition by from_cur, to_cur order by date) rn1, row_number() over(partition by from_cur, to_cur, rate order by date) rn2 from mytable t ) t group by from_cur, to_cur, rate, rn1 - rn2 ) t where cnt >= 3 order by from_cur, to_cur, max_date
Merci beaucoup pour l'aide rapide.J'ai peut-être spécifié, mais mon besoin est d'arriver à la première instance où le nombre> 2 .Je vais essayer de travailler sur votre requête pour obtenir la sortie attendue.
Lorsque la valeur change, marquez la ligne avec 1, sinon 0. Puis additionnez cette colonne ( flg
), vous avez maintenant des groupes consécutifs ( grp
). Utilisez grp
pour agréger, compter, afficher les dates minimum et maximum:
having count(1) >= 3
Si vous voulez un groupe spécifique après groupe en ajoutant: p>
select to_cur, from_cur, min(dt) dt_from, max(dt) dt_to, rate, count(1) cnt from ( select dt, to_cur, from_cur, rate, sum(flg) over (partition by to_cur, from_cur order by dt) grp from ( select dt, to_cur, from_cur, rate, case lag(rate) over (partition by to_cur, from_cur order by dt) when rate then 0 else 1 end flg from t)) group by grp, to_cur, from_cur, rate order by from_cur, to_cur, min(dt)
Merci beaucoup pour l'aide rapide.J'ai peut-être spécifié, mais mon besoin est d'arriver à la première instance où le nombre> 2 .Je vais essayer de travailler sur votre requête pour obtenir la sortie attendue.
C'est un problème d'espaces et d'îles, mais je le résoudrais simplement en soustrayant une séquence de la date. Et puis agréger:
select to_cur, from_cur, rate, min(date), max(date), count(*) as days_stale from (select r.*, row_number() over (partition by to_cur, from_cur, rate order by date) as seqnum from rates r ) r group by (date - seqnum * interval '1' day)