1
votes

Obtenez le nombre de jours consécutifs une valeur de champ est périmée

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.

 entrez la description de l'image ici

Résultat attendu

 entrez la description de l'image ici


0 commentaires

3 Réponses :


2
votes

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


1 commentaires

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.



2
votes

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:

démo de dbfiddle

  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)


1 commentaires

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.



0
votes

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)


0 commentaires