How to get the first and the last record per group in SQL Server 2008?
How about using ROW_NUMBER
:
SQL Fiddle
WITH Cte AS(
SELECT *,
RnAsc = ROW_NUMBER() OVER(PARTITION BY [group] ORDER BY val),
RnDesc = ROW_NUMBER() OVER(PARTITION BY [group] ORDER BY val DESC)
FROM tbl
)
SELECT
id, [group], val, start, [end]
FROM Cte
WHERE
RnAsc = 1 OR RnDesc = 1
ORDER BY [group], val
How to get the last record per group in SQL
You can use a ranking function and a common table expression.
WITH e AS
(
SELECT *,
ROW_NUMBER() OVER
(
PARTITION BY ApplicationId
ORDER BY CONVERT(datetime, [Date], 101) DESC, [Time] DESC
) AS Recency
FROM [Event]
)
SELECT *
FROM e
WHERE Recency = 1
Retrieving last record in each group from database - SQL Server 2005/2008
;with cteRowNumber as (
select COMPUTERNAME, SERIALNUMBER, USERNAME, LASTIP, LASTUPDATE, SOURCE,
row_number() over(partition by COMPUTERNAME order by LASTUPDATE desc) as RowNum
from YourTable
)
select COMPUTERNAME, SERIALNUMBER, USERNAME, LASTIP, LASTUPDATE, SOURCE
from cteRowNumber
where RowNum = 1
How to get first record out of each group from the result retrieved by using group by command
declare @T table (ID int, GroupID int, Qty int)
insert into @T values
(1, 1, 100),
(2, 1, 200),
(3, 1, 300),
(4, 2, 98),
(5, 2, 198),
(6, 3, 175),
(7, 3, 275),
(8, 3, 375),
(9, 4, 215)
;with cte as
(
select
ID,
GroupID,
Qty,
rank() over(partition by GroupID order by ID) as rn
from @T
)
select ID, GroupID, Qty
from cte
where rn = 1
Get the latest records per Group By SQL
The rank
window clause allows you to, well, rank rows according to some partitioning, and then you could just select the top ones:
SELECT oDate, oName, oItem, oQty, oRemarks
FROM (SELECT oDate, oName, oItem, oQty, oRemarks,
RANK() OVER (PARTITION BY oName ORDER BY oDate DESC) AS rk
FROM my_table) t
WHERE rk = 1
Get top 1 row of each group
;WITH cte AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY DocumentID ORDER BY DateCreated DESC) AS rn
FROM DocumentStatusLogs
)
SELECT *
FROM cte
WHERE rn = 1
If you expect 2 entries per day, then this will arbitrarily pick one. To get both entries for a day, use DENSE_RANK instead
As for normalised or not, it depends if you want to:
- maintain status in 2 places
- preserve status history
- ...
As it stands, you preserve status history. If you want latest status in the parent table too (which is denormalisation) you'd need a trigger to maintain "status" in the parent. or drop this status history table.
Selecting First and Last record from a table in SQL Server
Use MAX
and MIN
:
SELECT
MAX(titlenumber) AS MaxTitleNumber,
MIN(titlenumber) AS MinTitleNumber
FROM cataloguebase
Get the first and last record of each item for the month
You are getting the same quantities because you are aggregating by quantity
in the group by
as well as product. Your version of the query, properly written would be:
SELECT ProductID, MIN(Quantity) AS Starting, MAX(Quantity) AS Ending
FROM Records
WHERE DateAdded BETWEEN '2014-04-01' AND '2014-04-30'
GROUP BY ProductID;
However, this doesn't give you the first and last values. It only gives you the minimum and maximum ones. To get those values, use row_number()
and conditional aggregation:
SELECT ProductID,
MAX(CASE WHEN seqnum_asc = 1 THEN Quantity END) as Starting,
MAX(CASE WHEN seqnum_desc = 1 THEN Quantity END) as Ending
FROM (SELECT r.*,
row_number() over (partition by product order by dateadded asc) as seqnum_asc,
row_number() over (partition by product order by dateadded desc) as seqnum_desc
FROM Records r
) r
WHERE DateAdded BETWEEN '2014-04-01' AND '2014-04-30'
GROUP BY ProductID;
If you are using SQL Server 2012, then you can also use this with FIRST_VALUE()
and LAST_VALUE()
instead of row_number()
.
Select last records from table using group by
Assuming that the start and end dates will always be the highest values then you need to drop some of the columns from the GROUP BY
(having all the columns in the GROUP BY
is kinda like using DISTINCT
) and use an aggregate function on the other column:
SELECT UserId,
MAX(StartDate) AS StartDate,
MAX(EndDate) AS EndDate
FROM usersworktime
GROUP BY UserId;
Otherwise, if that isn't the case, you can use a CTE and ROW_NUMBER
:
WITH CTE AS(
SELECT UserID,
StartDate,
EndDate,
ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY UsersWordTimeID DESC) AS RN
FROM usersworktime)
SELECT UserID,
StartDate,
EndDate
FROM CTE
WHERE RN = 1;
Related Topics
Delphi: How to Pass a List as a Parameter to a SQL Query
How to Deep Copy a Set of Data, and Change Fk References to Point to All the Copies
How to Copy Structure and Contents of a Table, But with Separate Sequence
Printing Django Queryset SQL with ""
Convert SQL Server Date to Mm-Yyyy
Find Duplicate Records Based on Two Columns
Is It Ok Not to Use a Primary Key When I Don't Need One
Get List with Start and End Values from Table of Datetimes
Differencebetween Temporary Table and Table Variable in SQL 2008
How to Run Raw SQL with Kotlin's Exposed Library
Sql: Select Top 3 Records + Sum of Quantity
Mssql: Update Statement Avoiding the Check Constraint
How to Use Array_Agg() for Varchar[]