How to Select the most recent items by dates from another table - sql

I have two tables Projects and Plans, and I need get recent projects from the last plan by create date:
Projects:
ProjectId, PlanId, StartDate, EndDate
(guid) (guid) (datetime) (datetime)
-------------------------------------
00001, 00001, 1/1/2015 31/1/2015
00001, 00002, 3/2/2015 15/2/2015
00002, 00001, 1/2/2015 20/2/2015
00002, 00002, 1/2/2015 21/2/2015
00003, 00001, 1/3/2015 10/3/2015
Plans:
PlanId, CreateDate
(guid) (datetime)
--------------------
00001, 1/1/2015
00002, 5/2/2015
I wrote query that take single project from the last plan, but i can't write query to get many projects by single query.
Here my query:
SELECT TOP 1 pr.ProjectId,
pl.CreateDate,
pr.StartDate,
pr.EndDate
FROM Projects pr
INNER JOIN Plans pl
ON pr.PlanId = pl.PlanId
WHERE ProjectId = '000002'
ORDER BY pl.CreateDate DESC
Desired result is (all projects from the last plans):
ProjectId, PlanId, StartDate, EndDate
--------------------------------------
00001, 00002, 3/2/2015, 15/2/2015
00002, 00002, 1/2/2015, 21/2/2015
00003, 00001, 1/3/2015, 10/3/2015
UPDATE:
Gordon Linoff gave the good answer, but it wasn't solved my question, because both his queries don't take '00003' project (its last plan is '00001').
I wrote my query with 'OVER Clause' (Stanislovas Kalašnikovas note about it).
So I post full answer that solves my question for future googlers:
SELECT * FROM
(SELECT
result.ProjectId,
result.CreateDate,
result.StartDate,
result.EndDate,
ROW_NUMBER() OVER (PARTITION BY ProjectId ORDER BY CreateDate DESC) AS RowNumber
FROM (
SELECT pr.ProjectId AS ProjectId,
pl.CreateDate AS CreateDate,
pr.StartDate AS StartDate,
pr.EndDate AS EndDate
FROM Projects pr
INNER JOIN Plans pl ON pr.PlanId = pl.PlanId
--WHERE ProjectId IN ('000001', '000003') --Filter
) AS result
) AS result
WHERE result.RowNumber = 1

You can use a subquery to get the most recent plan. Then just join this to projects:
SELECT pr.ProjectId, pl.CreateDate, pr.StartDate, pr.EndDate
FROM (SELECT TOP 1 pl.*
FROM plans pl
ORDER BY pl.CreateDate DESC
) pl JOIN
Projects pr
ON pr.PlanId = pl.PlanId;
WHERE ProjectId = '000002'
An alternative method is to just use TOP WITH TIES:
SELECT TOP 1 WITH TIES pr.ProjectId, pl.CreateDate, pr.StartDate, pr.EndDate
FROM plans pl
Projects pr
ON pr.PlanId = pl.PlanId;
WHERE ProjectId = '000002'
ORDER BY pl.CreateDate DESC

This is example of ROW_NUMBER with 1 table, easy you can use It in your case.
CREATE TABLE #Test
(
Id NVARCHAR(100),
Data DATE
)
INSERT INTO #Test VALUES ('1', '2015-01-04'), ('1', '2015-01-07'), ('2', '2015-01-05'), ('2', '2015-01-08')
SELECT Id, Data
FROM (
SELECT Id, Data, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Data DESC) rn
FROM #Test
)x
WHERE rn > 1
DROP TABLE #Test

you can use datediff() e.g if you want to take the entries of last 10 days use:
SELECT pr.ProjectId,
pl.CreateDate,
pr.StartDate,
pr.EndDate
FROM Projects pr
INNER JOIN Plans pl
ON pr.PlanId = pl.PlanId
WHERE datediff(day,pl.CreateDate,getdate())<10

Related

Query keeps giving me duplicate records. How can I fix this?

I wrote a query which uses 2 temp tables. And then joins them into 1. However, I am seeing duplicate records in the student visit temp table. (Query is below). How could this be modified to remove the duplicate records of the visit temp table?
with clientbridge as (Select *
from (Select visitorid, --Visid
roomnumber,
room_id,
profid,
student_id,
ambc.datekey,
RANK() over(PARTITION BY visitorid,student_id,profid ORDER BY ambc.datekey desc) as rn
from university.course_office_hour_bridge cohd
--where student_id = '9999999-aaaa-6634-bbbb-96fa18a9046e'
)
where rn = 1 --visitorid = '999999999999999999999999999999'---'1111111111111111111111111111111' --and pai.datekey is not null --- 00000000000000000000000000
),
-----------------Data Header Table
studentvisit as
(SELECT
--Visit key will allow us to track everything they did within that visit.
distinct visid_visitorid,
--calcualted_visitorid,
uniquevisitkey,
--channel, -- says the room they're in. Channel might not be reliable would need to see how that operates
--office_list, -- add 7 to exact
--user_college,
--first_office_hour_name,
--first_question_time_attended,
studentaccountid_5,
profid_officenumber_8,
studentvisitstarttime,
room_id_115,
--date_time,
qqq144, --Course Name
qqq145, -- Course Office Hour Benefit
qqq146, --Course Office Hour ID
datekey
FROM university.office_hour_details ohd
--left_join niversity.course_office_hour_bridge cohd on ohd.visid_visitorid
where DateKey >='2022-10-01' --between '2022-10-01' and '2022-10-27'
and (qqq146 <> '')
)
select
*
from clientbridge ab inner join studentvisit sv on sv.visid_visitorid = cb.visitorid
I wrote a query which uses 2 temp tables. And then joins them into 1. However, I am seeing duplicate records in the student visit temp table. (Query is below). How could this be modified to remove the duplicate records of the visit temp table?
I think you may get have a better shot by joining the two datasets in the same query where you want the data ranked, otherwise your rank from query will be ignored within the results from the second query. Perhaps, something like ->
;with studentvisit as
(SELECT
--Visit key will allow us to track everything they did within that visit.
distinct visid_visitorid,
--calcualted_visitorid,
uniquevisitkey,
--channel, -- says the room they're in. Channel might not be reliable would need to see how that operates
--office_list, -- add 7 to exact
--user_college,
--first_office_hour_name,
--first_question_time_attended,
studentaccountid_5,
profid_officenumber_8,
studentvisitstarttime,
room_id_115,
--date_time,
qqq144, --Course Name
qqq145, -- Course Office Hour Benefit
qqq146, --Course Office Hour ID
datekey
FROM university.office_hour_details ohd
--left_join niversity.course_office_hour_bridge cohd on ohd.visid_visitorid
where DateKey >='2022-10-01' --between '2022-10-01' and '2022-10-27'
and (qqq146 <> '')
)
,clientbridge as (
Select
sv.*,
university.course_office_hour_bridge cohd, --Visid
roomnumber,
room_id,
profid,
student_id,
ambc.datekey,
RANK() over(PARTITION BY sv.visitorid,sv.student_id,sv,profid ORDER BY ambc.datekey desc) as rn
from university.course_office_hour_bridge cohd
inner join studentvisit sv on sv.visid_visitorid = cohd.visitorid
)
select
*
from clientbridge WHERE rn=1

Find similar sales orders in SQL

This is my first post.
I work at a manufacturing company and most of the products we are making are custom made.
We believe we can find some commonalities in the products we sale.
To do this, we need to analyze sales orders and compare them to all the sales orders in our system to find identical ones.
Here's an example in form of a SQL result:
etc...
+------------------------------+
| OrderId ProductCode Qty |
+------------------------------+
| SS1234 Widget1 1 |
| SS1234 Widget2 3 |
| SS1234 Widget3 1 |
+------------------------------+
I would like to find orders similar to SS1234, ie orders with the same products (widget1, widget2 and widget3) and the same quantities.
How do I do this in SQL Server 2008R2?
Thanks for your help!
Raf
I won't be able to test this before I go to bed for the evening. This is an overly verbose approach, but I wanted to grind this out as quickly as possible so I tried to use structure / syntax that I know well, instead of trying to write more concise, efficient code that would require I lean on the documentation. Basically, we're counting the number of items in each order, selecting a pair of order ids every time we find two matching line items, then we count how many times an exact pair of order IDs appears. Use inner joins to filter out pairs that matched fewer times than there are products in the order.
WITH
ProductCounts AS (
SELECT COUNT(OrderID) AS ProductCodesInOrder, OrderID
FROM Table
GROUP BY OrderID
), MatchingLineItems AS (
SELECT A.OrderID AS FirstOrderID, B.OrderID AS SecondOrderID
FROM Table AS A
INNER JOIN Table AS B
ON A.ProductCode = B.ProductCode AND A.Qty = B.Qty
ORDER BY FirstOrderID, SecondOrderID
), MatchTotals AS (
SELECT
COUNT(FirstOrderID) AS Matches, FirstOrderID, SecondOrderID
FROM MatchingLineItems
GROUP BY FirstOrderID, SecondOrderID
), FirstMatches AS (
SELECT MatchTotals.FirstOrderID, MatchTotals.SecondOrderID, MatchTotals.Matches
FROM MatchTotals
INNER JOIN ProductCounts
ON MatchTotals.FirstOrderID = ProductCounts.OrderID
WHERE MatchTotals.Matches = ProductCounts.ProductCodesInOrder
)
SELECT FirstMatches.FirstOrderID, FirstMatches.SecondOrderID
FROM FirstMatches
INNER JOIN ProductCounts
ON FirstMatches.SecondOrderID = ProductCounts.OrderID
WHERE FirstMatches.Matches = ProductCounts.ProductCodesInOrder
Setup:
CREATE TABLE #ord (
OrderId VARCHAR(20),
ProductCode VARCHAR(40),
qty int
)
INSERT INTO #ord (OrderId, ProductCode, Qty)
VALUES
('SS1234','Widget1',1)
,('SS1234','Widget2',3)
,('SS1234','Widget3',1)
,('SS1234a','Widget1',1)
,('SS1234a','Widget2',3)
,('SS1234a','Widget3',1)
,('xSS1234','Widget1',1)
,('xSS1234','Widget2',3)
,('xSS1234','Widget3',1)
,('xSS1234','Widget4',1)
,('ySS1234','Widget1',10)
,('ySS1234','Widget2',3)
,('ySS1234','Widget3',1)
,('zSS1234','Widget2',3)
,('zSS1234','Widget3',1)
;
Query:
with CTE as (
select distinct
o.OrderID, ca.ProductString, ca.QtyString
from #ord o
cross apply (
SELECT
STUFF((
SELECT
', ' + o2.ProductCode
FROM #ord o2
WHERE o.OrderID = o2.OrderID
ORDER BY o2.ProductCode
FOR XML PATH ('')
)
, 1, 1, '')
, STUFF((
SELECT
', ' + cast(o2.Qty as varchar)
FROM #ord o2
WHERE o.OrderID = o2.OrderID
ORDER BY o2.ProductCode
FOR XML PATH ('')
)
, 1, 1, '')
) ca (ProductString, QtyString)
)
select
ProductString, QtyString, count(*) Num_Orders
from CTE
group by
ProductString, QtyString
having
count(*) > 1
order by
Num_Orders DESC
, ProductString
Result:
ProductString QtyString Num_Orders
Widget1, Widget2, Widget3 1, 3, 1 2
See: http://rextester.com/DJEN59714

SQL Join on nearest available date

I currently have these tables:
CREATE TABLE #SECURITY_TEMP (ID CHAR(30))
CREATE TABLE #SECURITY_TEMP_PRICE_HISTORY (ID CHAR(30), PRICEDATE DATE, PRICE FLOAT)
CREATE TABLE #SECURITY_POST (ID CHAR(30), SECPOS int)
INSERT INTO #SECURITY_TEMP (ID) VALUES ('APPL') ,('VOD'),('VOW3'), ('AAA')
INSERT INTO #SECURITY_TEMP_PRICE_HISTORY (ID,PRICEDATE, PRICE) VALUES
('APPL', '20150101',10.4), ('APPL', '20150116',15.4), ('APPL', '20150124',22.4),
('VOD', '20150101', 30.5), ('VOD', '20150116',16.5), ('VOD', '20150124',16.5),
('VOW3', '20150101', 45.5), ('VOW3', '20150116',48.8) ,('VOW3', '20150124',50.55),
('AAA', '20100118', 0.002)
INSERT INTO #SECURITY_POST (ID,SECPOS) VALUES ('APPL', 100), ('VOD', 350), ('VOW3', 400)
I want to have a clean table that shows me the security ID, the security position and the latest available price for that security when a date is passed.
Now when I do the following:
SELECT sec.ID, sec.SECPOS, t.PRICE
FROM #SECURITY_POST as SEC INNER JOIN #SECURITY_TEMP_PRICE_HISTORY as t
ON sec.ID = t.ID
WHERE t.PriceDate = '20150101'
GROUP BY sec.ID, secPos, t.price
I get the correct result
1. ID SECPOS PRICE
2. APPL 100 10.4
3. VOD 350 30.5
4. VOW3 400 45.5
However, there may be individual circumstances where, the price of a stock is not available. In that sense, I therefore want to be able to get the most recent price available.
Doing
SELECT sec.ID, sec.SECPOS, t.PRICE
FROM #SECURITY_POST as SEC INNER JOIN
#SECURITY_TEMP_PRICE_HISTORY as t
ON sec.ID = t.ID
WHERE t.PriceDate = '20150117'
GROUP BY sec.ID, secPos, t.price
Returns 0 rows because of no data, and doing
SELECT sec.ID, sec.SECPOS, t.PRICE
FROM #SECURITY_POST as SEC INNER JOIN
#SECURITY_TEMP_PRICE_HISTORY as t
ON sec.ID = t.ID
WHERE t.PriceDate <= '20150117'
GROUP BY sec.ID, sec.secPos, t.price
HAVING sec.secpos <> 0
Returns duplicate rows.
I have tried loads of different methodologies and I just cannot get the output I want. Furthermore, I would also like to be able to get one column with the price nearest a date (call it START_DATE) and one column with the price nearest a second date (call it END_DATE) and one column that is going to be the position Price#END_DATE - Price#START_DATE. The price is always taken from the same #SECURITY_TEMP_PRICE_HISTORY.
However, my SQL knowledge is just embarrassing, and I could not figure out a good efficient way of doing this. Any help would be appreciated. Please also note that the #SECURITY_PRICE_HISTORY table may contain more securities than the #SECURITY_POST Table.
This should do the trick. OUTER APPLY is a join operator that (like CROSS APPLY) allows a derived table to have an outer reference.
SELECT
s.ID,
s.SecPos,
t.Price
t.PriceDate
FROM
#SECURITY_POST s
OUTER APPLY (
SELECT TOP 1 *
FROM #SECURITY_TEMP_PRICE_HISTORY t
WHERE
s.ID = t.ID
AND t.PriceDate <= '20150117'
ORDER BY t.PriceDate DESC
) t
;
You may also want to consider flagging security prices that are very old, or limiting the lookup for the most recent security to a certain period (a week or a month or something).
Make sure that your price history table has an index with (ID, PriceDate) so that the subquery lookups can use range seeks and your performance can be good. Make sure you do any date math on the security table, not the history table, or you will force the price-lookup subquery to be non-sargable, which would be bad for performance as the range seeks would not be possible.
If no price is found for the security, OUTER APPLY will still allow the row to exist, so the price will show as NULL. If you want securities to not be shown when no appropriate price is found, use CROSS APPLY.
For your second part of the question, you can do this with two OUTER APPLY operations, like so:
DECLARE
#StartDate date = '20150101',
#EndDate date = '20150118';
SELECT
S.ID,
S.SecPos,
StartDate = B.PriceDate,
StartPrice = B.Price,
EndDate = E.PriceDate,
EndPrice = E.Price,
Position = B.Price - E.Price
FROM
#SECURITY_POST S
OUTER APPLY (
SELECT TOP 1 *
FROM #SECURITY_TEMP_PRICE_HISTORY B
WHERE
S.ID = B.ID
AND B.PriceDate <= #StartDate
ORDER BY B.PriceDate DESC
) B
OUTER APPLY (
SELECT TOP 1 *
FROM #SECURITY_TEMP_PRICE_HISTORY E
WHERE
S.ID = E.ID
AND E.PriceDate <= #EndDate
ORDER BY E.PriceDate DESC
) E
;
With your data this yields the following result set:
ID SecPos StartDate StartPrice EndDate EndPrice Position
---- ------ ---------- ---------- ---------- -------- --------
APPL 100 2015-01-01 10.4 2015-01-16 15.4 -5
VOD 350 2015-01-01 30.5 2015-01-16 16.5 14
VOW3 400 2015-01-01 45.5 2015-01-16 48.8 -3.3
Last, while not all agree, I would encourage you to name your ID columns with the table name as in SecurityID instead of ID. In my experience the use of ID only leads to problems.
Note: there is a way to solve this problem using the Row_Number() windowing function. If you have relatively few price points compared to the number of stocks, and you're looking up prices for most of the stocks in the history table, then you might get better performance with that method. However, if there are a great number of price points per stock, or you're filtering to just a few stocks, you may get better performance with the method I've shown you.

Difference of data per day

I have a table called Addim and the data looks like:
TName Idate Number
Integrated 3/21/2012 26984013
Integrated 3/20/2012 26959226
Integrated 3/19/2012 26933190
I want the output as:
Idate Diff
3/21/2012 24787
3/20/2012 26036
I did something like this:
Select Count(*),Idate
from dbo.Addim
group by Idate
But i am getting output like this:
Idate Diff
03/21/2012 1
03/20/2012 1
basically what it does is it takes the difference from previous day
for example:
for 3/21/2012 the diff is 26984013(3/21/2012)-26959226(3/20/2012) = 24787
and for
3/20/2012 is 26959226(3/20/2012)-26933190(3/19/2012) = 26036
the trick is to join the table back to itself for the previous day, like this:
DECLARE #Addim table (TName varchar(10), Idate datetime,Number int)
INSERT INTO #Addim VALUES ('Integrated','3/21/2012',26984013)
INSERT INTO #Addim VALUES ('Integrated','3/20/2012',26959226)
INSERT INTO #Addim VALUES ('Integrated','3/19/2012',26933190)
SELECT
a.TName,a.Idate, a.Number-b.Number
FROM #Addim a
INNER JOIN #Addim b ON a.TName=b.TName AND a.Idate=b.Idate+1
OUTPUT:
TName Idate
---------- ----------------------- -----------
Integrated 2012-03-21 00:00:00.000 24787
Integrated 2012-03-20 00:00:00.000 26036
(2 row(s) affected)
I wasn't sure the significance of TName, so I joined on that column too, assuming that you'd have multiple different values there as well. You can easily remove it from the join if it is not used like that.
Try this:
;WITH CTE AS
(
SELECT TName, Idate, Number, ROW_NUMBER() OVER(ORDER BY Idate) Corr
FROM #Temp1--YourTable
)
SELECT A.Idate, A.number - B.number Diff
FROM CTE A
INNER JOIN CTE B
ON A.Corr = B.Corr + 1
This assumes one record per day, but it will work even if there are missing days.

CTE-common table exp in t-sql

I have a problem with the following query:
WITH CTE_1 (stu_id
,meet_doc_id
,doc_name
,stu_name
,dob
,done
,date_meet_doc)
AS
(SELECT stu_id
,meet_doc_id
,doc_name
,stu_name
,dob
,CASE
WHEN (PATINDEX('%SMOKING%',act.VALUE)) THEN
'LMDO'
WHEN (PATINDEX('%NOT SMOKING%',act.VALUE)) THEN
'LMD1'
WHEN (ISNULL(CAST(act.VALUE as varchar(max)),'')='') THEN
'CLEAR'
ELSE
'CLEAR'
END done
,date_meet_doc
FROM
abc INNER JOIN
INNER JOIN
INNER JOIN
WHERE multiple conditions
)
SELECT * FROM CTE_1 one
WHERE date =(SELECT MAX(DATE) FROM CTE_1 two WHERE two.stu_id=one.stu_id
AND one.doc_name=two.doc_name)
ORDER BY stu_name,dob
;
The result set of the inner query(CTE_1) for three student(for eg) will be something like
stu_id meet_doc_id doc_name stu_name dob value date
101 0104 AD AM 15/06/1950 LMDO 2011-02-15
101 0105 AD AM 15/06/1950 CLEAR 2011-02-18
101 0106 AD AM 15/06/1950 CLEAR 2011-02-25
102 0107 AD AK 12/08/1987 CLEAR 2011-03-28
102 0108 AD AK 12/08/1987 LDMO 2011-04-29
103 0109 PK LMP 13/07/1970 CLEAR 2011-03-28
103 0110 PK LMP 13/07/1970 CLEAR 2011-05-12
AND when i execute the whole query my result set will be
stu_id meet_doc_id doc_name stu_name dob value date
101 0106 AD AM 15/06/1950 CLEAR 2011-02-25
102 0108 AD AK 12/19/1987 LDMO 2011-04-29
103 0110 PK LMP 13/07/1970 CLEAR 2011-05-12
What do i have to do to change the outer query to select only those value ie LDMO or LMD1 for a particular student and whose doctor is same?
Suppose if the student meets the doc multiple times and if in any of the cases if the student gets a LMDO or LMD1 then it should pick only that record irrespective of the date.
I am expecting my resultset to be something like:
stu_id meet_doc_id doc_name stu_name dob value date
101 0104 AD AM 15/06/1950 LMDO 2011-02-15
102 0107 AD AK 12/08/1987 CLEAR 2011-03-28
103 0110 PK LMP 13/07/1970 CLEAR 2011-05-12
The logic behind it is if the stu_id is same and the doc_name is same and if there exists a value either LMDO or LMD1 then show that record if not show the record which has CLEAR.
Simply i want to remove the MAX(date) and place a condition for the whole reporting period of that particular stu_id with the same doc_name.
Edit: To add a high-level description of what I did.
You want to get your original information (CTE_1) filtered down by 2 possible criteria. The easiest way to do this is to first establish those criteria in their own result sets. So, we have a subquery that returns a list of (Student, Doc, Max(Date)) combinations and a similar list that is filtered on the LMDO/LMD1 values.
Now, we need to LEFT JOIN to the filtered data since there may not be results for each student.
So now you have a list of Student/Doc/MaxDate and also a possible FilteredDate.
The final step is to JOIN that result set to the original data (CTE_1). Since the FilteredDate takes precedence, we check for that first through the ISNULL function and, if it isn't present, we use the MaxDate instead.
First, I'd change the original query to the following as I think you'll see some performance gains on large data-sets by eliminating the correlated subquery:
SELECT *
FROM CTE_1 one
INNER JOIN
(SELECT stu_id, doc_name, max(date) maxdate FROM CTE_1 group by stu_id,doc_name) two
ON one.stu_id = two.stu_id and one.doc_name = two.doc_name
ORDER BY stu_name,dob
Now, we can add an additional, similar, join to get the max(date) where the Value is in your desired list. We'll need to shuffle the joins around a little bit too.
SELECT realdata.*
FROM
((SELECT stu_id, doc_name, max(date) maxdate FROM CTE_1 group by stu_id,doc_name) maxdt
LEFT JOIN
(SELECT stu_id, doc_name, max(date) maxdate FROM CTE_1
WHERE value in ('LMDO', 'LMD1')
group by stu_id,doc_name) filtered
ON maxdt.stu_id = filtered.stu_id and maxdt.doc_name = filtered.doc_name)
INNER JOIN CTE_1 realdata
ON realdata.stu_id = maxdt.stu_id and realdata.doc_name = maxdt.doc_name
and realdata.date = isnull(filtered.maxdate, maxdt.maxdate)
ORDER BY realdata.stu_name,realdata.dob
declare #TestTable
as table
(stu_id int,
meet_doc_id char(4),
doc_name char(2),
stu_name varchar(3),
dob date,
value varchar(5),
date_meet_doc date)
insert into #TestTable
(stu_id,meet_doc_id,doc_name,stu_name,dob,value,date_meet_doc)
values
(101,'0104','AD','AM', '19500615','LDMO' ,'2011-02-15'),
(101,'0105','AD','AM', '19500615','CLEAR','2011-02-18'),
(101,'0106','AD','AM', '19500615','CLEAR','2011-02-25'),
(102,'0107','AD','AK', '19870812','CLEAR','2011-03-28'),
(102,'0108','AD','AK', '19870812','LDMO' ,'2011-04-29'),
(103,'0109','PK','LMP','19700713','CLEAR','2011-03-28'),
(103,'0110','PK','LMP','19700713','CLEAR','2011-05-12');
WITH CTE_1 (stu_id
,meet_doc_id
,doc_name
,stu_name
,dob
,done
,date_meet_doc)
AS
(SELECT stu_id
,meet_doc_id
,doc_name
,stu_name
,dob
,value
,date_meet_doc
FROM #TestTable
),
CTE_2 as(
SELECT *,row_number() over (partition by stu_id order by case when done in ('LDMO','LDM1') then 0 else 1 end, date_meet_doc desc) rn FROM CTE_1)
select stu_id
,meet_doc_id
,doc_name
,stu_name
,dob
,value
,date_meet_doc
from CTE_2 where rn=1
;
Thanks to those who tried to understand but gave up since i couldnt explain it.
Thanks Again guys :)