views:

55

answers:

1
SELECT  
            P.PK_PatientId
            ,PV.PK_PatientVisitId
            --, PV.LastUpdated
            , ISNULL(P.FName,'')+ ', '+ ISNULL(P.LName,'') AS NAME
            , MAX(TVP.PK_VisitProcedureId) AS PK_VisitProcedureId
            , MAX(PV.LastUpdated)AS DateSort
        FROM         
            dbo.M_Patient AS P 
                INNER JOIN
            dbo.M_PatientVisit AS PV 
                    ON 
                        P.PK_PatientId = PV.FK_PatientId 
                INNER JOIN
            dbo.TX_VisitProcedure AS TVP 
                    ON 
                        PV.PK_PatientVisitId = TVP.FK_PatientVisitId
        WHERE     
            (P.IsActive = 1) 
                AND 
            (PV.IsActive = 1) 
                AND 
            (TVP.IsActive = 1)
            --  AND
            --PV.LastUpdated=GETDATE()
        GROUP BY PK_PatientId, PK_PatientVisitId, ISNULL(P.FName,'')+ ', '+ ISNULL(P.LName,'')--, PV.LastUpdated
        --HAVING MAX(TVP.PK_VisitProcedureId)=PK_VisitProcedureId
        ORDER BY 
            P.PK_PatientId DESC
            , DateSort DESC
            ,PV.PK_PatientVisitId DESC

PK_PatientId PK_PatientVisitId NAME                  PK_VisitProcedureId    DateSort
------------ ----------------- --------------------  ------------------- -----------------------
3            5                 TRAVIS, BARKER           8                   2010-08-31 00:00:00.000
3            3                 TRAVIS, BARKER           6                   2010-08-31 00:00:00.000
2            2                 BRIAN, IGNOTOWICZ        5                   2010-08-23 00:00:00.000
1            4                 WILLIAM, HENWOOD         7                   2010-08-31 00:00:00.000
1            1                 WILLIAM, HENWOOD         4                   2010-08-31 00:00:00.000

(5 row(s) affected)

Above mentioned query is returning me the above given result. I want to get only distinct rows for each patient where PK_VisitProcedureId is maximum in the result set. I think this can be done using Having clause in the above query but not been able to get it.

Desired Result set is

PK_PatientId PK_PatientVisitId NAME                  PK_VisitProcedureId    DateSort
------------ ----------------- --------------------  ------------------- -----------------------
3            5                 TRAVIS, BARKER           8                   2010-08-31 00:00:00.000
2            2                 BRIAN, IGNOTOWICZ        5                   2010-08-23 00:00:00.000
1            4                 WILLIAM, HENWOOD         7                   2010-08-31 00:00:00.000
+2  A: 
SELECT PK_PatientId, PK_PatientVisitId, NAME, PK_VisitProcedureId, DateSort
FROM   (SELECT t.*, ROW_NUMBER() OVER(PARTITION BY PK_PatientId ORDER BY    
        PK_VisitProcedureId DESC) r
     FROM   (SELECT P.PK_PatientId, PV.PK_PatientVisitId,
                     ISNULL(P.FName, '') + ', ' + ISNULL(P.LName, '') AS NAME,
                     MAX(TVP.PK_VisitProcedureId) AS PK_VisitProcedureId,
                     MAX(PV.LastUpdated) AS DateSort
              FROM   dbo.M_Patient AS P
              INNER  JOIN dbo.M_PatientVisit AS PV
              ON     P.PK_PatientId = PV.FK_PatientId
              INNER  JOIN dbo.TX_VisitProcedure AS TVP
              ON     PV.PK_PatientVisitId = TVP.FK_PatientVisitId
              WHERE  (P.IsActive = 1)
              AND    (PV.IsActive = 1)
              AND    (TVP.IsActive = 1)
              GROUP  BY PK_PatientId, PK_PatientVisitId,
                        ISNULL(P.FName, '') + ', ' + ISNULL(P.LName, '')
              ORDER  BY P.PK_PatientId DESC, DateSort DESC, PV.PK_PatientVisitId DESC
  ) t ) e
  WHERE  r = 1;

Also you can try: (sub-query select latest visits for each patient)

 SELECT P.PK_PatientId, PV.PK_PatientVisitId,
         ISNULL(P.FName, '') + ', ' + ISNULL(P.LName, '') AS NAME,
         MAX(TVP.PK_VisitProcedureId) AS PK_VisitProcedureId, DateSort
  FROM   (SELECT PV.FK_PatientId PatientId, MAX(PK_PatientVisitId) PatientVisitId,
                  MAX(PV.LastUpdated) AS DateSort
           FROM   dbo.M_PatientVisit AS PV AND (PV.IsActive = 1)
           GROUP  BY PV.FK_PatientId) AS LatestVisits, M_Patient AS p, TX_VisitProcedure AS tvp
  WHERE  p.PK_PatientId = LatestVisits.PatientId
  AND    tvp.FK_PatientVisitId = LatestVisits.PatientVisitId
  AND    (P.IsActive = 1)
  AND    (TVP.IsActive = 1)
  GROUP  BY PK_PatientId, PK_PatientVisitId, ISNULL(P.FName, '') + ', ' + ISNULL(P.LName, ''),
            DateSort
  ORDER  BY 1 DESC, DateSort DESC
Michael Pakhantsov
@Michael: Isn't it possible with having clause. I am expecting that it could be done by using Having clause only and need not have any nested or corelated query. Is it possible.
Shantanu Gupta
@Shantanu Gupta, probably it is possible if you provide some details, query looks like that you try select patients and their procedure in last visit. (Correct me if I wrong).
Michael Pakhantsov
@Michael: yes you are right. I am trying to do exactly what you are thinking
Shantanu Gupta
@Shantanu Gupta, Does table TX_VisitProcedure have field FK_PatientId?
Michael Pakhantsov
@Michael: No. There are three tables. P, PV, TX. P's PK is FK in PV. and PV's FK is in TX. P is related to PV as one to many and PV is related to TX as one to many
Shantanu Gupta
@Shantanu Gupta, added another query, so please check results.
Michael Pakhantsov
@Michael: I could be wrong, but your first query looks like it is using Oracle-specific syntax - Shantanu is using SQLServer.
Mark Bannister
@Mark, from 2005 version sql server have windowed (analytical functions), not too much as oracle, but for typical queries quite enough, http://msdn.microsoft.com/en-us/library/ms189461.aspx
Michael Pakhantsov