I have a table, with the following columns:
PK1 PK2 ID DATE Value flag
I do a calculation that involves taking the max value per ID.
select id,
max(value)
from table
group by id
I want to mark the flag on the rows that I am using. If id and the max(value) correspond to multiple rows flag the one with the max date. If they have the same id,max(value) and max(date) flag exactly one of those rows (don't care which at that point)
Any ideas?
开发者_开发技巧Thanks!
For SQL2005+ maybe something like this. (Assuming that "Mark" means update the flag column)
WITH cte AS
(
SELECT PK1, PK2, ID, DATE, Value, flag,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY value desc, date desc) AS RN
FROM table
)
UPDATE cte
SET flag=CASE WHEN RN=1 THEN 1 ELSE 0 END
With SQL Server 2005 or above, you can do the following:
SELECT x.*
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY value DESC, date DESC) AS RN
FROM table
) x
WHERE x.RN = 1
Why does this NOT work?
update table
set flag = '1'
where id in (select id from (SELECT PK1, PK2, id, date,value,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY value DESC, date DESC) AS RN
FROM table) t where RN = 1)
EDIT: the below statement WILL work if you don't want to (or can't in some sql versions) use a cte
The above will not work because, as martin says below, the id is still in the list.
however, the below will work if someone prefereds not to use a cte.(Not nearly as elegant as Martin's solution though)
update table
set flag = '1'
where convert(varchar,PK1)+convert(varchar,PK2) in (select convert(varchar,PK1)+convert(varchar,PK2) from (SELECT PK1, PK2, id, date,value,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY value DESC, date DESC) AS RN
FROM table) t where RN = 1)
精彩评论