Avatar of biotec
biotec
 asked on

SQL query to only pull most recent value

The query below will pull what I need but pulls all obsvalues and I only want it to pull the most recent. The completeddate is probably what needs to be used in some sort of nested select but I'm not sure how to do this and return values for all rather than just values for one person.

SELECT distinct obsvalue, p.person_id, p.last_name, p.first_name, p.person_nbr, o2.completeddate
FROM order_ o2
INNER JOIN ncsuds_lab_test_desc d ON RTRIM(o2.actText) = RTRIM(d.test_desc) and d.order_ind = 'Y' AND d.selected_diag_id = 42
inner join person p on o2.person_id = p.person_id
WHERE o2.obsvalue IS NOT NULL
AND ISNUMERIC(o2.obsvalue) = 1
and o2.completeddate > '20150101'
order by completeddate desc
DatabasesMicrosoft SQL ServerSQL

Avatar of undefined
Last Comment
biotec

8/22/2022 - Mon
Jim Horn

<knee-jerk reaction>

Which column defines 'most recent'?  If you mean the most recent o2.completedate, then you'll need a MAX.

SELECT obsvalue, p.person_id, p.last_name, p.first_name, p.person_nbr, 
   MAX(o2.completeddate) as most_recent_completeddate
FROM order_ o2
   INNER JOIN ncsuds_lab_test_desc d ON RTRIM(o2.actText) = RTRIM(d.test_desc) and d.order_ind = 'Y' AND d.selected_diag_id = 42
   INNER JOIN person p on o2.person_id = p.person_id
WHERE o2.obsvalue IS NOT NULL
   AND ISNUMERIC(o2.obsvalue) = 1
   AND o2.completeddate > '20150101'
GROUP BY obsvalue, p.person_id, p.last_name, p.first_name, p.person_nbr
ORDER BY completeddate desc

Open in new window

btw note the use of indentation and capitalizing all SELECT .. FROM ... keywords.  Makes it easier to read.   Also I removed the DISTINCT as the GROUP BY handles that.

Check out SQL Server GROUP BY Solutions for some extra info on grouping.
Pavel Celba

I would try ROW_NUMBER() here:
SELECT * FROM (
  SELECT ROW_NUMBER() OVER (p.person_id, p.person_nbr ORDER BY completeddate desc) rowno, 
         obsvalue, p.person_id, p.last_name, p.first_name, p.person_nbr, o2.completeddate
    FROM order_ o2
   INNER JOIN ncsuds_lab_test_desc d ON RTRIM(o2.actText) = RTRIM(d.test_desc) and d.order_ind = 'Y' AND d.selected_diag_id = 42
   inner join person p on o2.person_id = p.person_id
   WHERE o2.obsvalue IS NOT NULL
     AND ISNUMERIC(o2.obsvalue) = 1
     and o2.completeddate > '20150101') insl
  WHERE rowno = 1 

Open in new window

biotec

ASKER
This is getting closer but still returns duplicates for many of the persons we're returning the values for. In other words the first two rows in the returned data set are the same person with a value for Sep and another for Nov. It is returning both and I'd only want it to return the entry for Nov.
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
ASKER CERTIFIED SOLUTION
Pavel Celba

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
biotec

ASKER
There is a syntax error near the first Order By. Not sure that can be wrapped inside parens like that.
Pavel Celba

The ROW_NUMBER() requires SQL Server 2005 or newer. The OVER (PARTITION BY ... ORDER BY ...) clause should be OK because it belongs to the ROW_NUMBER().
More info: https://msdn.microsoft.com/en-us/library/ms186734.aspx

If you are using different SQL engine then tell the version please.

BTW, multiplicities on output can also be caused by the INNER JOIN ncsuds_lab_test_desc  definition. To join two tables via text description column is not a standard. What is the reason to join ncsuds_lab_test_desc table?
biotec

ASKER
I don't quite understand what the Row_Number Over Partition does but it seemed to work. Thanks
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Jim Horn

>This is getting closer but still returns duplicates for many of the persons we're returning the values for.
Please show us some sample data, both your data source and what the above queries are returning.
Pavel Celba

ROW_NUMBER() generates line numbers for your data and the OVER() defines rules for such numbering, namely grouping (partitioning) and the order of the data.

To get the latest result for each person we used p.person_id for grouping (p.person_nbr is not necessary probably) and ordered the data by  completeddate DESC.

Thanks to the descending order the latest result has ROW_NUMBER() = 1 for each person.

I agree the ROW_NUMBER() is a little bit unclear at the first view.

BTW, this part of your query is still unclear to me:
   INNER JOIN ncsuds_lab_test_desc d ON RTRIM(o2.actText) = RTRIM(d.test_desc) and d.order_ind = 'Y' AND d.selected_diag_id = 42

but that's not important maybe.
biotec

ASKER
Thank you this is helpful. I'm still unclear on the inner join too, but it doesn't seem to filter anything out that I need so I have to trust the vendor on this one.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck