This question already has an answer here:
SQL Server query assistance needed
(1 answer)
Closed 6 years ago.
I have a UNION ALL query that I'm getting incorrect results for. I'm supposed to get about 1100 hundred records. Please see query...
select
Pop, planID, PopFull, ApptDate, intake1,FollowUP2,FollowupCode, rn, '5133'
from
(Select *, row_number() over (partition by planID order BY AddedDate asc) as rn from Vinfo) t
where
rn = 1 and ApptDate >='12/1/2014' and ApptDate <='12/31/2015'
Union All
select
Pop, planID, PopFull, ApptDate, intake1, FollowUP2, FollowupCode, rn, '5133'
from
(Select *,row_number() over (partition by PlanID order BY AddedDate DESC) as rn from Vinfo) t
where
rn = 1 and ApptDate >='12/1/2014' and ApptDate <='12/31/2015'
So what I'm trying to do is SELECT all the info and in the first SELECT statement, I'm trying to get a VALUE for INTAKE when ADDEDDATE is the lowest (earliest).
I'm doing the UNION all because in the second SELECT statement, I'm trying to get a value for FOLLOWup when ADDEDDATE is the oldest (most recent).
The values for INTAKE AND FOLLOWUP might be different, but doesnt have to be. I'm trying to track the difference.
However when I run this query, I get double the records. Is there a way for me to run this query so that I can get the correct number of records (1100) and get value for INTAKE and if there's a change in value for FOLLOWUP I will see that in the same row?
Instead of seeing double of everything. Basically the way it's running now is if PLANID is 1023 and Intake for EARLIEST date is B then it will show me B for FollowUP as well. in Addition if, FollowUP for LATEST date is C then it will show me C for Intake and FollowUP in the row below it.
EDIT:
select Pop,planID,PopFull,ApptDate, intake1,FollowUP2,FollowupCode, '5133'
from (select *,
row_number() over (partition by planID order BY AddedDate asc) as rn_first,
row_number() over (partition by PlanID order BY AddedDate DESC) as rn_last
from VInfo
) t
where t.rn_first = 1 or rn_last = 1
and ApptDate >='12/1/2014' and ApptDate <='12/31/2015'
Ran this but doesn't give right results
You will obviously get duplicates for those rows which have only one instance of Pop, planID, PopFull, ApptDate, intake1, FollowUP2, FollowupCode combination - i.e. both ASC and DESC return one row and rn=1 for ASC and DESC sorting.
UNION ALL does allow duplicates from top and bottom rowsets.
You may try UNION instead.
Also, as suggested before, you may count both ROW_NUMBERS in single select:
select *
from
(
select v.*,
row_number() over (partition by PlanID order BY AddedDate asc) as rn_first,
row_number() over (partition by PlanID order BY AddedDate DESC) as rn_last
from Vinfo v
) t
where t.rn_first = 1 or rn_last = 1
Related
This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 10 months ago.
I have such a situation. I need to make a code work so that it selects only one PVISBN (Item Number) based on PVLICP (license plate) (I need to get only the first row from 2 that I am getting back).
TableSeven AS (
SELECT PVISBN, PVWHS, PVLICP, PVRZNE, PVRLOC, PVAZNE, PVALOC, PVLPRG,
ROW_NUMBER() OVER (PARTITION BY PVISBN, PVRZNE ORDER BY PVLICP --, PVRLOC, PVAZNE, PVALOC, PVLPRG
ASC) AS rn
FROM [REPIT].[LEVYDTA].[WHSPDVT]
WHERE PVSPDT BETWEEN #Last2WeekDATE AND #LWDate
--AND PVISBN='0164556221'
) ,
TableTwelve AS (
SELECT PVISBN, PVWHS, PVLICP, PVRZNE, PVRLOC, PVAZNE, PVALOC, PVLPRG, rn
FROM TableSeven
WHERE rn = 1
),
I keep getting 2 rows and should get only the 1st one
If someone may have an idea, I will appreciate.
Assuming "Oldest" and "Lowest" is the same, you can use aggregation:
SELECT PVISBN, MIN(PVLICP) as PVLICP
FROM yourtable
GROUP BY PVISBN;
To your comment, if you are wanting all columns in the output, then consider window functions (also called Analytics Functions or Ordered Analytics Functions) to help identify the min() for a group/window (PVISBN in this case) and then filter:
SELECT *
FROM
(
SELECT yourtable.*, ROW_NUMBER() OVER (PARTITION BY PVISBN ORDER BY PVLICP ASC) as rn
FROM yourtable
) dt
WHERE rn = 1;
That will generate a row_number, starting at 1 for each row for each distinct PVISBN (you can run just the subquery to see how that looks). Then we just filter for rn of 1, which will be the record for that PVISBN with the lowest PVLICP.
I think this would be helpful for you
SELECT PVISBN, PVWHS, MIN(PVLICP) as PVLICP , ------------ FROM tablename WHERE PVLICP IS NOT NULL or PVLICP <> '' group by PVISBN;
I have table that looks like the following
I have to select every second record per PatientID that would give the following result (my last query returns this result)
I then have to select the record with the oldest date which would be the following (this is the end result I want)
What I have done so far: I have a CTE that gets all the data I need
WITH cte
AS
(
SELECT visit.PatientTreatmentVisitID, mat.PatientMatchID,pat.PatientID,visit.RegimenDate AS VisitDate,
ROW_NUMBER() OVER(PARTITION BY mat.PatientMatchID, pat.PatientID ORDER BY visit.VisitDate ASC) AS RowNumber
FROM tblPatient pat INNER JOIN tblPatientMatch mat ON mat.PatientID = pat.PatientID
LEFT JOIN tblPatientTreatmentVisit visit ON visit.PatientID = pat.PatientID
)
I then write a query against the CTE but so far I can only return the second row for each patientID
SELECT *
FROM
(
SELECT PatientTreatmentVisitID,PatientMatchID,PatientID, VisitDate, RowNumber FROM cte
) as X
WHERE RowNumber = 2
How do I return the record with the oldest date only? Is there perhaps a MIN() function that I could be including somewhere?
If I follow you correctly, you can just order your existing resultset and retain the top row only.
In standard SQL, you would write this using a FETCH clause:
SELECT *
FROM (
SELECT
visit.PatientTreatmentVisitID,
mat.PatientMatchID,
pat.PatientID,
visit.RegimenDate AS VisitDate,
ROW_NUMBER() OVER(PARTITION BY mat.PatientMatchID, pat.PatientID ORDER BY visit.VisitDate ASC) AS rn
FROM tblPatient pat
INNER JOIN tblPatientMatch mat ON mat.PatientID = pat.PatientID
LEFT JOIN tblPatientTreatmentVisit visit ON visit.PatientID = pat.PatientID
) t
WHERE rn = 2
ORDER BY VisitDate
OFFSET 0 ROWS FETCH FIRST 1 ROW ONLY
This syntax is supported in Postgres, Oracle, SQL Server (and possibly other databases).
If you need to get oldest date from all selected dates (every second row for each patient ID) then you can try window function Min:
SELECT * FROM
(
SELECT *, MIN(VisitDate) OVER (Order By VisitDate) MinDate
FROM
(
SELECT PatientTreatmentVisitID,PatientMatchID,PatientID, VisitDate,
RowNumber FROM cte
) as X
WHERE RowNumber = 2
) Y
WHERE VisitDate=MinDate
Or you can use SELECT TOP statement. The SELECT TOP clause allows you to limit the number of rows returned in a query result set:
SELECT TOP 1 PatientTreatmentVisitID,PatientMatchID,PatientID, VisitDate FROM
(
SELECT *
FROM
(
SELECT PatientTreatmentVisitID,PatientMatchID,PatientID, VisitDate,
RowNumber FROM cte
) as X
WHERE RowNumber = 2
) Y
ORDER BY VisitDate
For simplicity add order desc on date column and use TOP to get the first row only
SELECT TOP 1 *
FROM
(
SELECT PatientTreatmentVisitID,PatientMatchID,PatientID, VisitDate, RowNumber FROM cte
) as X
WHERE RowNumber = 2
order by VisitDate desc
I have a table called TABLE_SCREW where I want to get the latest records for each code.
For example, in the table below you should obtain the records with ids 3 and 7.
I am a newbie in sql and I hope you can help me.
You could use:
SELECT TOP 1 WITH TIES *
FROM TABLE_SCREW
ORDER BY ROW_NUMBER() OVER(PARTITION BY CODE ORDER BY Date DESC);
Another approach(may have better performance):
SELECT * -- here * should be replaced with actual column names
FROM (SELECT *,ROW_NUMBER() OVER(PARTITION BY CODE ORDER BY Date DESC) AS rn
FROM TABLE_SCREW) sub
WHERE sub.rn = 1;
I'm having trouble constructing a query that can find consecutive values meeting a condition. Example data below, note that Date is sorted DESC and is grouped by ID.
To be selected, for each ID, the most recent RESULT must be 'Fail', and what I need back is the earliest date in that run of 'Fails'. For ID==1, only the 1st two values are of interest (the last doesn't count due to prior 'Complete'. ID==2 doesn't count at all, failing the first condition, and for ID==3, only the first value matters.
A result table might be:
The trick seems to be doing some type of run-length encoding, but even with several attempts manipulating ROW_NUM and an attempt at the tabibitosan method for grouping consecutive values, I've been unable to gain traction.
Any help would be appreciated.
If your database supports window functions, you can do
select id, case when result='Fail' then earliest_fail_date end earliest_fail_date
from (
select t.*
,row_number() over(partition by id order by dt desc) rn
,min(case when result = 'Fail' then dt end) over(partition by id) earliest_fail_date
from tablename t
) x
where rn=1
Use row_number to get the latest row in the table. min() over() to get the earliest fail date for each id. If the first row has status Fail, you select the earliest_fail_date or else it would be null.
It should be noted that the expected result for id=1 is wrong. It should be 2016-09-20 as it is the earliest fail date.
Edit: Having re-read the question, i think this is what you might be looking for. Getting the minimum Fail date from the latest consecutive groups of Fail rows.
with grps as (
select t.*,row_number() over(partition by id order by dt desc) rn
,row_number() over(partition by id order by dt)-row_number() over(partition by id,result order by dt) grp
from tablename t
)
,maxfailgrp as (
select g.*,
max(case when result = 'Fail' then grp end) over(partition by id) maxgrp
from grps g
)
select id,
case when result = 'Fail' then (select min(dt) from maxfailgrp where id = m.id and grp=m.maxgrp) end earliest_fail_date
from maxfailgrp m
where rn=1
Sample Demo
Working in a school district I have a database that contains information about students' Education Plans. I'm using Management Studio to access a SQL Server 2012 database. I need to grab the information from their 2nd most recent plan. Here are the columns.
Database Name is PlansAnoka
Table name is dbo.plans
Columns:
PlanID (primary key)
StudentID (these would all be unique for each student)
PlanDate (this is the column that I want to use as the date to pull the 2nd most recent record.
Meeting Date (this is just another data point that I need)
I know how to create a query to grab the most recent one, but not the 2nd most recent one. AND I need 2nd most recent record for EACH student. Any help would be appreciated!
Use the ROW_NUMBER function and partition by StudentID:
WITH A AS
(
SELECT
StudentID ,
PlanDate ,
MeetingDate,
ROW_NUMBER() OVER(PARTITION BY StudentID ORDER BY PlanDate DESC) rownum
FROM dbo.plans
)
SELECT * FROM a
WHERE rownum=2
use row_number if you want get n'th record:
select * from
(select studentid ,
plandata ,
row_number() over(partition by plandata order by plandata desc) rn
from dbo.plans) t
where t.rn=2 -- or n
Please try this:
select * from
(select *, row_number() over (partition by StudentID order by PlanDate desc) Rank
from dbo.plans) p
where p.Rank = 2
Reference link: https://msdn.microsoft.com/en-us/library/ms186734.aspx
Try this one;
select * from
(
select *, ROW_NUMBER()
over(partition by StudentID order by plandate desc)
as Row from dbo.plans
) temp
WHERE temp.Row = 2