Reputation: 293
I have an SQL Database and in it a table called InventoryAllocations. In the table I have multiple entries for DocumentID's and want to retrieve the last entry for each unique DocumentID. I can retrieve just one by doing
SELECT top(1) [UID]
,[RecordStatusID]
,[CreatedDate]
,[CreatedTime]
,[CreatedByID]
,[OperationType]
,[InventoryLocationID]
,[DocumentTypeID]
,[DocumentID]
,[SOJPersonnelID]
,[InventorySerialisedItemID]
,[TransactionQty]
,[TransactionInventoryStatusID]
,[Completed]
,[CreatedByType]
,[RecordTimeStamp]
FROM [CPData].[dbo].[InventoryAllocations]
order by DocumentID desc
but I want it to bring back a list containing all the unique DocumentID's.
Upvotes: 29
Views: 87844
Reputation: 33581
Basically like this.
with cte as
(
SELECT [UID]
, [RecordStatusID]
, [CreatedDate]
, [CreatedTime]
, [CreatedByID]
, [OperationType]
, [InventoryLocationID]
, [DocumentTypeID]
, [DocumentID]
, [SOJPersonnelID]
, [InventorySerialisedItemID]
, [TransactionQty]
, [TransactionInventoryStatusID]
, [Completed]
, [CreatedByType]
, [RecordTimeStamp]
, ROW_NUMBER() over (partition by DocumentID order by RecordTimeStamp desc) as RowNum
FROM [CPData].[dbo].[InventoryAllocations]
)
select [UID]
, [RecordStatusID]
, [CreatedDate]
, [CreatedTime]
, [CreatedByID]
, [OperationType]
, [InventoryLocationID]
, [DocumentTypeID]
, [DocumentID]
, [SOJPersonnelID]
, [InventorySerialisedItemID]
, [TransactionQty]
, [TransactionInventoryStatusID]
, [Completed]
, [CreatedByType]
, [RecordTimeStamp]
from cte
where RowNum = 1
order by DocumentID desc
Upvotes: 0
Reputation: 214
You can use a RowNumber() Window Function.
SELECT * FROM(
SELECT
ROW_NUMBER() OVER(PARTITION BY [DOCUMENTID] ORDER BY [RecordTimeStamp] DESC) AS RowNumber,
,[RecordStatusID]
,[CreatedDate]
,[CreatedTime]
,[CreatedByID]
,[OperationType]
,[InventoryLocationID]
,[DocumentTypeID]
,[DocumentID]
,[SOJPersonnelID]
,[InventorySerialisedItemID]
,[TransactionQty]
,[TransactionInventoryStatusID]
,[Completed]
,[CreatedByType]
,[RecordTimeStamp]
FROM [CPData].[dbo].[InventoryAllocations] ) as A
WHERE RowNumber = 1
Upvotes: 10
Reputation: 3101
SELECT TOP 1 WITH TIES
[UID]
,[RecordStatusID]
,[CreatedDate]
,[CreatedTime]
,[CreatedByID]
,[OperationType]
,[InventoryLocationID]
,[DocumentTypeID]
,[DocumentID]
,[SOJPersonnelID]
,[InventorySerialisedItemID]
,[TransactionQty]
,[TransactionInventoryStatusID]
,[Completed]
,[CreatedByType]
,[RecordTimeStamp]
FROM
[CPData].[dbo].[InventoryAllocations]
ORDER BY
ROW_NUMBER() OVER(PARTITION BY DocumentID ORDER BY [RecordTimeStamp] DESC);
TOP 1
works with WITH TIES
here.
WITH TIES
means that when ORDER BY = 1
, then SELECT
takes this record (because of TOP 1
) and all others that have ORDER BY = 1
(because of WITH TIES
).
Upvotes: 65
Reputation: 2364
This gives each record a row, taking each document ID and then giving the latest created_date a row_number of 1, and each row before that an increment of 1. We then select the records with a rowno of 1 to get the latest created date per document ID:
SELECT [UID]
,[RecordStatusID]
,[CreatedDate]
,[CreatedTime]
,[CreatedByID]
,[OperationType]
,[InventoryLocationID]
,[DocumentTypeID]
,[DocumentID]
,[SOJPersonnelID]
,[InventorySerialisedItemID]
,[TransactionQty]
,[TransactionInventoryStatusID]
,[Completed]
,[CreatedByType]
,[RecordTimeStamp]
FROM
(
SELECT
[UID]
,[RecordStatusID]
,[CreatedDate]
,[CreatedTime]
,[CreatedByID]
,[OperationType]
,[InventoryLocationID]
,[DocumentTypeID]
,[DocumentID]
,[SOJPersonnelID]
,[InventorySerialisedItemID]
,[TransactionQty]
,[TransactionInventoryStatusID]
,[Completed]
,[CreatedByType]
,[RecordTimeStamp]
,ROW_NUMBER() OVER (PARTITION BY DOCUMENT_ID ORDER BY CreatedDate) DESC AS ROWNO
FROM [CPData].[dbo].[InventoryAllocations]
)
WHERE ROWNO = 1
Upvotes: 1