2010-11-30 7 views
2

J'ai 2 tables. pour cet exemple, je n'utiliserai qu'un seul enregistrement d'utilisateur. La première table a le nom d'utilisateur et une date d'évaluation en tant que telle:SQL Server 2005 - Comment prendre un enregistrement à partir d'une table et faire une boucle dans une autre table à la recherche de correspondance

USER EVALDATE 
-------------- 
bobr 6/7/2010 
bobr 9/20/2010 
bobr 9/21/2010 

Le tableau ci-dessus doit être joint contre cette table d'historique de l'utilisateur, qui a l'histoire de l'ID de et les dates auxquelles ils étaient en cours de validité, à chercher un match (la date NULL signifie en cours):

USER STARTDATE ENDDATE 
---------------------------- 
bobr 2/20/2006 4/18/2010 
bobr2 4/19/2010 9/7/2010 
bobr 9/8/2010 null 

ce que je suis en train de faire dans SQL Server 2005 est de prendre le premier enregistrement de la première table, en boucle à travers la deuxième table et quand (si) EVALDATE est dans l'une de ces plages de dates et les ID correspondent, puis marque cet enregistrement de la première table comme valide. Le code actuel extrait l'enregistrement de la première table et s'exécute sur toutes les lignes de la deuxième table et extrait un enregistrement pour chaque evaldate invalide, de sorte qu'il extrait un enregistrement lorsqu'il est joint à la seconde table car l'evaldate n'est pas entre les dates du premier enregistrement sur la table d'historique, même si l'enregistrement est correct car l'evaldate est entre les dates de début et de fin du troisième enregistrement dans la table d'historique.

J'espère que cela a du sens! Dans quelque chose comme SAS, je peux créer un tableau et faire une boucle en vérifiant chaque enregistrement de la table d'historique. Comment est-ce que je fais cela en SQL? Ce que j'essayais de faire était juste de mettre à jour la première table avec un drapeau si les dates des enregistrements ne sont pas valides. Des idées? Merci!!!

Répondre

1

Essayez ceci:

SELECT [USER] 
     ,[EVALDATE] 
     ,CASE WHEN (SELECT COUNT(*) 
        FROM [UserStartEndDates] b 
        WHERE [a].[USER] = [b].[User] 
          AND [EVALDATE] BETWEEN [STARTDATE] 
               AND COALESE([ENDDATE],[EVALDATE]) 
       ) > 0 THEN 1 
      ELSE 0 
     END AS [IsValid] 
FROM [Evaluations] a 
+0

Cela fonctionne! J'ai ajouté une instruction AND dans la clause where pour vérifier que les userids correspondent et qu'il semble faire ce que j'ai besoin de faire. Cela semble si simple mais je ne pouvais pas arriver à ça! Merci Brad, je l'apprécie vraiment. – ramos

0

essayer quelque chose comme:

select * from [table2] t2 
join [table1] t1 on t1.user = t2.user 
--or better yet the foreign key 
where t1.user = t2.user and t1.evaldate  
between t2.startdate and t2.enddate 
+0

Salut, j'ai essayé celui-ci d'abord, mais je n'ai pas réussi à le faire fonctionner. Peut-être que j'ai mal compris quelque chose à propos du code? – ramos

+0

cela retournera tous les utilisateurs dans la table2 qui sont également dans la table1 qui ont un evaldate entre le startdate et le endate de table2. Si l'utilisateur n'est pas dans la table 2, ils n'apparaîtront pas. Il se pourrait que j'ai mal compris votre question. Quel message avez-vous reçu quand ça n'a pas marché? – Ramy

+0

Eh bien, il a couru mais quand il est revenu j'ai eu 4 enregistrements: 3 enregistrements de la table d'histoire du premier enregistrement, un pour chaque evaldate de la première table et ensuite le dernier enregistrement de la table d'histoire fusionné avec le 6/7/2010 record de la première table. – ramos

1

Vous pouvez essayer quelque chose comme

Select * 
FROM Users u INNER JOIN 
     UserHistory uh ON u.User = uh.User 
         AND u.EvalDate BETWEEN uh.StartDate 
             AND  ISNULL(uh.EndDate, u.EvalDate) 

EDIT

Essayez ceci pour toutes les valeurs de User

Select u.*, 
     CASE 
      WHEN uh.User IS NULL 
       THEN 'Invalid' 
      ELSE 'Valid' 
     END Validity 
FROM Users u LEFT JOIN 
     UserHistory uh ON u.User = uh.User 
         AND u.EvalDate BETWEEN uh.StartDate 
             AND  ISNULL(uh.EndDate, u.EvalDate) 
+0

Sauf que cela masque les évaluations qui ne sont pas valides car le paramètre USER ne se termine pas dans l'une ou l'autre table. – Brad

+0

oui vrai, j'ai besoin de la table d'origine pour sortir tous les enregistrements et soit être marqué comme valide ou invalide. Cela a fonctionné, mais cela supprime les enregistrements invalides. Pourtant, le code fonctionne! Merci Astander !! – ramos

+0

Modifiez l'INNER JOIN à LEFT JOIN puis, en utilisant CASE pour vérifier l'existence. Va ajouter cela à la réponse rapide comme X-) –