Remove all but last entry by column - sql-server

I would like to select distinct NAME and delete rows where the ID <> Max(ID) for that NAME.
The table is as follows ...
NAME DATE ID
BudgetX.dbo.Persons 2015-02-13 13:53:38.780 1
BudgetX.dbo.Persons 2015-02-13 13:53:38.780 2
BudgetX.dbo.ILFS 2015-02-13 14:29:55.347 3
BudgetX.dbo.ILFS 2015-02-13 14:29:55.347 4
BudgetX.dbo.ILFS 2015-02-13 14:30:10.813 5
I would like to remove all but rows 2 and 5.
Any ideas appreciated.
Thanks, RR

You could use a CTE + ROW_NUMBER:
WITH CTE AS
(
SELECT Name, Date, ID,
RN = ROW_NUMBER() OVER (PARTITION BY Name ORDER BY ID DESC)
FROM dbo.TableName
)
DELETE FROM CTE WHERE RN > 1

Related

Case when first instance of unique ID

I'm in Snowflake and am trying to mark the first occurrence of a unique ID in a column. I've been playing around with first_value but am not really getting anywhere.
So my data looks something like this:
ID Date
123 1/2019
123 2/2019
123 3/2019
234 2/2019
234 3/2019
And ideally I want something like this:
ID Date First?
123 1/2019 1
123 2/2019 0
123 3/2019 0
234 2/2019 1
234 3/2019 0
How do I accomplish this?
You want ROW_NUMBER:
SELECT
ID,
Date,
IFF(ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date) = 1, 1, 0) AS First
FROM
schema.table
ORDER BY ID, Date
;
This checks whether the current row is the first date for the ID, and if it is, assigns a value of 1 (otherwise 0).
LAG can also be used to solve this..
SELECT id
,date
,lag(id) over (partition by id order by date) is null as first
FROM table_name;
Which can be also done with FIRST_VALUE like
SELECT id
,date
,first_value(id) over (partition by id order by date) = date as first
FROM table_name;
If your intention is to retrieve the first occurrence of a unique ID in a column then the row_number() or the dense_rank() function can help.
with cte as
(
select ID, Date,
row_number() over (partition by ID order by date) as row_number
from table1
)
select * from cte where row_number = 1;
with cte as
(
select ID, Date,
dense_rank() over (partition by ID order by date) as rank
from stack1
)
select * from cte where rank = 1;

SQL Server query should return max value records

I have table like this:
id_Seq_No emp_name Current_Property_value
-----------------------------------------------
1 John 100
2 Peter 200
3 Pollard 50
4 John 500
I want the max record value of particular employee.
For example, John has 2 records seq_no 1, 4. I want 4th seq_no Current_Property_Value in single query.
Select
max(id_Seq_No)
from
t1
where
emp_name = 'John'
To get the Current_Property_value, just order the results by id_Seq_No and get the first one:
SELECT
TOP 1 Current_Property_value
FROM
table
WHERE
emp_name = 'John'
ORDER BY
id_Seq_No DESC
this will give highest for all tied employees
select top 1 with ties
id_Seq_No,emp_name,Current_Property_value
from
table
order by
row_number() over (partition by emp_name order by Current_Property_value desc)
You can use ROW_NUMBER with CTE.
Query
;WITH CTE AS(
SELECT rn = ROW_NUMBER() OVER(
PARTITION BY emp_name
ORDER BY id_Seq_No DESC
), *
FROM your_table_name
WHERE emp_name = 'John'
)
SELECT * FROM CTE
WHERE rn = 1;

How can I find duplicate on one column

I have a SQL server database,and there are many duplicate in one(RanjePhoneNumber) column.
I am trying to select rows from a table that have duplicates in RanjePhoneNumber column and they have a same CityId.
My Table:
RanjePhoneNumber ContactId CityId
776323 280739 7
342261 186372 80
468284 75980 7
776323 101969 9
362875 170242 13
224519 164914 7
342261 203606 55
776323 280733 7
342261 203602 80
My expected results:
RanjePhoneNumber ContactId CityId
776323 280739 7
342261 186372 80
776323 280733 7
342261 203602 80
Group by those two columns:
SELECT RanjePhoneNumber, CityID
FROM dbo.TableName
GROUP BY RanjePhoneNumber, CityID
HAVING COUNT(*) > 1
If you want to select all columns you could use a ranking function:
WITH CTE AS
(
SELECT t.*, Cnt = COUNT(*) OVER (PARTITION BY RanjePhoneNumber, CityID)
FROM dbo.TableName
)
SELECT RanjePhoneNumber, ContactId, CityId
FROM CTE
WHERE Cnt > 1
If you don't want to find all rows which belong to this "duplicate-group" but only all but the first, use the ROW_NUMBER approach the other answer has shown.
;with cte
as
(select
Ranjephonenumber,
contactid,
cityid,
row_number() over (partition by Ranjephonenumber,cityid order by cityid) as rn
from table
)
select
Ranjephonenumber,contactid,city from cte where rn>1

How to select last id(where id >0) fod each group in SQL Server 2008

I want to select last record of price column of my table where my value of column is greater than zero. How can I do that?
My stored procedure is :
SELECT
id, name, price
FROM
messages
WHERE
id IN (SELECT MAX(id)
FROM messages
WHERE price > 0
GROUP BY name)
The problem is that this code select max id that price is greater than zero not last id. Means select id=2 and id=6
But in last id of group (frank) price is zero but this stored procedure select id=2 while I want stored procedure select only id =6
id name price
--------------
1 frank 1000
2 frank 500
3 frank 0
4 john 200
5 john 100
6 john 20
There are multiple ways to approach this. Following your method, though, you just need to move the price comparison to the outer query:
SELECT id, name, price
FROM messages
WHERE price > 0 AND
id IN (SELECT MAX(id)
FROM messages
GROUP BY name
);
I would be more inclined to write this as:
select m.*
from (select m.*,
row_number() over (partition by name order by id desc) as seqnum
from messages m
) m
where seqnum = 1 and price > 0;
with cte as (
select row_number() over(partition by id order by id desc) rn,
id,name,price
from messages
)
select id,name,price
from cte
where rn=1 and price>0
Something like this.

SQL Server 2008 R2 GROUP BY or OVER

I have this table:
ID COLOR TYPE DATE
-------------------------------
1 blue A 2012.02.05
2 white V 2010.10.23
3 white V 2014.03.05
4 black S 2013.02.14
I'd like to select only the ID, but in case of 2nd and 3rd rows I want to select the 3rd row because of its latest DATE value.
I have tried this query but it gives back all the two rows:
SELECT
ID, MAX(DATE) OVER(PARTITION BY COLOR, TYPE)
FROM
TABLE
WHERE
...
How can I select just one column value while I group the rows by other columns, please?
;WITH CTE AS
(
SELECT * , ROW_NUMBER() OVER (PARTITION BY COLOR,[TYPE] ORDER BY [DATE] DESC) rn
FROM TableName
)
SELECT ID
,COLOR
,[TYPE]
,[DATE]
FROM CTE
WHERE rn = 1
OR
SELECT ID
,COLOR
,[TYPE]
,[DATE]
FROM
(
SELECT * , ROW_NUMBER() OVER (PARTITION BY COLOR,[TYPE] ORDER BY [DATE] DESC) rn
FROM TableName
) A
WHERE rn = 1

Resources