SQL using Rank and Row_Number with Order by

SQL using Rank and Row_Number with Order by



I am using SSMS 2018 and have a table similar to this:


CREATE TABLE DxList (DocID INT, Dx VARCHAR(255), DxDate DATE, CreateDate DATETIME);

INSERT INTO DxList (DocID, Dx, DxDate, CreateDate)
VALUES (6018, 'OSDD', '10/01/2015', '10/09/2015 12:27');

INSERT INTO DxList (DocID, Dx, DxDate, CreateDate)
VALUES (6018, 'ADHD', '10/01/2015', '10/09/2015 18:14');


SELECT *
FROM DxList

DocID Dx DxDate CreateDate
6018 OSDD 10/1/2015 10/9/2015 12:27
6018 ADHD 10/1/2015 10/9/2015 18:14



I'd like to get the most recent Dx based on the DxDate. Row_number would work, however, if there is a tie like the one above (10/1/2015), I want the most recent to be based on the CreateDate instead.


Dx


DxDate


Row_number


CreateDate



In this case, I'd like my result to be:


DocID Dx DxDate CreateDate
6018 ADHD 10/1/2015 10/9/2015 18:14



I believe I can use Rank() with this query but I'm not sure how. This is my query so far:


Rank()


SELECT DISTINCT
DocID,
Dx,
DxDate,
CreateDate,
rownum1,
rank1
FROM (SELECT
DocID,
Dx,
DxDate,
CreateDate,
RANK() OVER (PARTITION BY DocID ORDER BY DxDate DESC) AS rank1,
ROW_NUMBER() OVER (PARTITION BY DocID ORDER BY DxDate DESC) AS rownum1
FROM DxList) b
WHERE rownum1 = 1



I believe I'm looking for something like:



Order By (Case When rank1=rank1 then CreateDate else DxDate End) DESC



Of course this doesn't work because I need some sort of iteration and can't put it in the subquery.
I also cannot use any derived tables to solve this issue. Is this possible?
Much appreciated!






i think your sample output is wrong because DocID is different but according to your description it would be same

– Zaynul Abadin Tuhin
Sep 9 '18 at 4:17





3 Answers
3



You should be able to use ROW_NUMBER with a two-tiered ORDER BY clause:


ROW_NUMBER


ORDER BY


SELECT DocID, Dx, DxDate, CreateDate
FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY DocID ORDER BY DxDate DESC, CreateDate DESC) rn
FROM DxList
) t
WHERE rn = 1;



The only major change in the above query versus what you had in mind is that two records with the same DocID and DxDate values would then be compared by the CreateDate to decide which one is really the "first."


DocID


DxDate


CreateDate




Demo



Note: In your demo the two records have different DocID values, but I think you intended for them to have the same value. In the demo link above, I have changed the two records to have the same DocID value, and the logic is working.


DocID


DocID






I could scream by how complicated I made it. You are correct--this will work. In my real data, it is more complicated and DocID is actually different. However, I will change the sample data to make it more clear since I partitioned by the DocID. Thank you so much!

– WixLove
Sep 9 '18 at 4:41



You can use only ROW_NUMBER() and ORDER BY CreateDate it will work.



ROW_NUMBER() OVER (PARTITION BY DocID ORDER BY CreateDate DESC) AS rownum1



According to your sample data just need below query


SELECT top 1 *
FROM DxList
order by DxDate desc,CreateDate desc



But According to your description follow @Tim provided query



here in this link both query you will find



https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=44fdd4b2e849137cebe9df837ac41a39


DocID Dx DxDate CreateDate
6018 ADHD 01/10/2015 00:00:00 09/10/2015 18:14:00



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)