2013-07-04 2 views
1

Voici une table qui stocke la valeur de personal_id et date:Tri des données par l'instruction SQL

Person_ID Effective_Date  End Effective_Date 
    1)6335   24/02/1999 
    2)6335   09/07/1998 
    3)6335   26/06/1998 

et la table de sortie doit être comme

Person_ID Effective_Date  End Effective_Date 
    1)6335   24/02/1999   31/12/9999 
    2)6335   09/07/1998   23/02/1999 
    3)6335   26/06/1998   08/07/1998 

La logique sera très facile si je mis à jour en utilisant le code java. Mais peut-il être fait en utilisant une instruction SQL? J'ai besoin de quelqu'un pour me donner la logique de le faire. Ma date d'entrée en vigueur actuelle sera toujours un jour avant la prochaine date d'entrée en vigueur. Disons que ma date d'entrée en vigueur pour la ligne numéro 2 est le 09/07/1988 alors ma date d'entrée en vigueur pour la ligne numéro 1 devrait être un jour avant (08/07/1988). Alors que ma date d'entrée en vigueur pour la date d'effet maximale sera toujours 31/12/9999.

+4

ce qui est ur logique pour la fin efeectiveDate? –

+1

Pouvez-vous nous s'il vous plaît ce que vous essayez de faire ici? – heretolearn

+0

Salut, je viens de modifier ma question s'il vous plaît jeter un oeil 1er. Désolé pour ne pas avoir clarifié la question à ce sujet. – goh6319

Répondre

1

J'espère que cela vous aide. Exécutez la requête et vérifiez les résultats.

DECLARE @tbl table (ID int, D1 DATETIME, D2 DATETIME) 

INSERT INTO @tbl 
select 1,'2/28/2013','2/28/2013' 
union all 
select 2,'3/2/2013','3/2/2013' 
union all 
select 3,'4/2/2013','4/2/2013' 
union all 
select 4,'4/6/2013','4/6/2013' 
union all 
select 5,'5/21/2013','5/21/2013' 
union all 
select 6,'6/10/2013','6/10/2013' 

SELECT * FROM @tbl 

UPDATE t1 
SET t1.D2= DATEADD(DAY, -1, t2.D2) 
FROM @tbl t1 
    CROSS JOIN @tbl t2 
WHERE t2.D1=(SELECT min(D1) 
       FROM @tbl t 
       WHERE D1>t1.D1) 


SELECT * FROM @tbl 

UPDATE @tbl 
SET D2 = '12/31/9999' 
WHERE D2 = (SELECT TOP 1 D2 FROM @tbl ORDER BY D2 DESC) 

SELECT * FROM @tbl 

Cela pourrait ne pas être le cas le plus efficace, mais il suppose que vous avez initialement mêmes valeurs dans les deux D1 et D2.

+0

Salut mec merci pour votre aide aussi. Votre logique peut bien fonctionner. mais je préfère beaucoup la réponse d'Alex. Quoi qu'il en soit, merci beaucoup. – goh6319

+0

bienvenue mec :) – Saksham

0
UPDATE personal_id SET [End Effective_Date] = To_date('31/12/9999', 'dd/mm/yyyy') 
WHERE Person_ID = 6335 AND Effective_Date = To_date('24/02/1999', 'dd/mm/yyyy') 
+0

Salut mec, je viens de modifier ma question tout à l'heure. S'il vous plaît jeter un oeil 1er. (^. ^) Merci. – goh6319

0

encore vous devez avoir les couples de EFFECTIVE_DATE la prochaine effective_date

SELECT P1.Effective_Date, P2.Effective_Date 
FROM personal_id P1, personal_id P2 where P1.Effective_Date < P2.Effective_Date 
GROUP BY P1.Effective_Date 
HAVING P2.Effective_Date = MIN(P2.Effective_Date) 

Je pense qu'il doit être mieux avec une jointure

après: vous faire la mise à jour un sur la Fin Date d'entrée en vigueur

+0

Salut katria, que diriez-vous si la fin efficace n'est pas fournir et il doit être le contrôle par la logique en SQL qui est toujours un jour avant la prochaine date d'entrée en vigueur? – goh6319

1

Vous pouvez utiliser la fonction lead pour regarder vers l'avenir à la ligne suivante et obtenir son entrée en vigueur:

select person_id, effective_date, 
    lead(effective_date) 
    over (partition by person_id order by effective_date) as lead_date 
from t42; 

PERSON_ID EFFECTIVE_DATE LEAD_DATE 
---------- -------------- --------- 
     6335 26-JUN-98  09-JUL-98 
     6335 09-JUL-98  24-FEB-99 
     6335 24-FEB-99 

Vous pouvez alors l'utiliser pour effectuer la mise à jour. La commande merge rend ce assez facile:

merge into t42 
using (
    select person_id, effective_date, 
    lead(effective_date) 
     over (partition by person_id order by effective_date) as lead_date 
    from t42 
) t 
on (t42.person_id = t.person_id and t42.effective_date = t.effective_date) 
when matched then 
update set t42.end_effective_date = 
    case 
    when t.lead_date is null then date '9999-12-31' 
    else t.lead_date - 1 
    end; 

3 rows merged. 

select * from t42; 

PERSON_ID EFFECTIVE_DATE END_EFFECTIVE_DATE 
---------- -------------- ------------------ 
     6335 26-JUN-98  08-JUL-98   
     6335 09-JUL-98  23-FEB-99   
     6335 24-FEB-99  31-DEC-99   

La clause using a l'extrait ci-dessus de faire la date de la ligne précédente. La clause on correspond à la table d'origine. La ligne correspondante met à jour la date d'entrée en vigueur jusqu'au jour précédant la date d'entrée en vigueur, ou s'il n'y a pas de valeur principale (pour la ligne "actuelle" la plus récente). date à partir de 1999.

votre question fait référence à une mise à jour, mais si vous voulez juste la date de fin comme une colonne calculée dans votre jeu de résultats, il est beaucoup plus simple:

select person_id, effective_date, 
    case when lead_date is null then date '9999-12-31' 
    else lead_date - 1 end as end_effective_date 
from (
    select person_id, effective_date, 
    lead(effective_date) 
     over (partition by person_id order by effective_date) as lead_date 
    from t42 
); 

PERSON_ID EFFECTIVE_DATE END_EFFECTIVE_DATE 
---------- -------------- ------------------ 
     6335 26-JUN-98  08-JUL-98   
     6335 09-JUL-98  23-FEB-99   
     6335 24-FEB-99  31-DEC-99   
+0

Salut mec, très impressionnant par la déclaration SQL que vous avez écrit tout à l'heure. cela m'aide beaucoup et l'instruction est claire. Vous me fournissez une direction claire pour le faire. Merci beaucoup. – goh6319