Oracle
 sql >> Base de données >  >> RDS >> Oracle

Réduire les enregistrements de date uniquement si la valeur ne change pas - Oracle SQL

Cela semble un peu compliqué, donc je serais intéressé par des améliorations.

select distinct emp_id,
    nvl(x_start_date,
        lag(x_start_date)
            over (partition by emp_id
                order by rn)) as start_date,
    nvl(x_end_date,
        lead(x_end_date)
            over (partition by emp_id
                order by rn nulls first))
                    as end_date,
        rating,
        department
from (
    select emp_id, start_date, end_date, rating, department,
        case start_date
            when lag(end_date)
                over (partition by emp_id, rating, department
                    order by start_date) then null
            else start_date end as x_start_date,
        case end_date
            when lead(start_date)
                over (partition by emp_id, rating, department
                    order by start_date) then null
            else end_date end as x_end_date,
        rownum as rn
    from table1
)
where x_start_date is not null or x_end_date is not null
order by emp_id, start_date
/

Avec ces données de test :

    EMP_ID START_DA END_DATE RA DEPARTMENT               SALARY
---------- -------- -------- -- -------------------- ----------
      2000 01012010 01012011 A  HR                         9000
      2000 01012011 01012012 A  HR                        10000
      2000 01012012 01012013 A+ HR                        20000
      2000 01012013 01012014 A  HR                        20000
      2000 01012014 12319999 A  HR                        21000
      3000 01012011 01012012 B  Operations                50000
      3000 01012012 12319999 B  Operations                60000
      4000 07012011 07012012 B  Operations                50000
      4000 07012012 07012013 B  Operations                50000
      4000 07012013 12319999 B  Operations                60000

J'obtiens ceci :

    EMP_ID START_DA END_DATE RA DEPARTMENT
---------- -------- -------- -- --------------------
      2000 01012010 01012012 A  HR
      2000 01012012 01012013 A+ HR
      2000 01012013 12319999 A  HR
      3000 01012011 12319999 B  Operations
      4000 07012011 12319999 B  Operations

J'ai aussi essayé avec un emp_id (4000 ) qui avait trois plages de dates contiguës, et il s'en est bien occupé - le where externe clause fait disparaître les entrées intermédiaires, essentiellement. Modifié pour ajouter  :Fonctionne désormais également avec vos plages de dates supplémentaires pour 2000/A , puisque j'ai corrigé l'ordre dans le lead externe /lag partitions.

La requête interne efface tout sauf la première date de début et la dernière date de fin pour un bloc contigu, et la requête externe utilise un deuxième tour de lead et lag pour les fusionner en lignes identiques, que le distinct puis s'effondre.

Je suppose start_date et end_date sont DATE champs, pas VARCHAR2 , et vous avez NLS_DATE_FORMAT défini sur MMDDYYYY . S'ils sont stockés sous forme de chaînes, ce qui est une mauvaise idée, vous avez besoin de to_date() à plusieurs endroits pour que la commande fonctionne correctement.