Reputation: 6945
I have simple SQL Server query:
declare @table table (id int, name nvarchar(5), deleted bit)
insert into @table(id, name, deleted) values(1, 'A1', 0)
insert into @table(id, name, deleted) values(2, 'A1', 0)
insert into @table(id, name, deleted) values(3, 'A1', 0)
insert into @table(id, name, deleted) values(4, 'A1', 1)
insert into @table(id, name, deleted) values(5, 'A2', 0)
insert into @table(id, name, deleted) values(6, 'A2', 0)
select
max(id) as id,
name
from @table
where deleted = 0
group by name
it returns to rows
id |name
--------------
3 |A1
6 |A2
but should return only one
id |name
--------------
6 |A2
since last (or max) id of A1 is deleted.
How to fix my query.
Thanks a lot.
Upvotes: 0
Views: 211
Reputation: 39393
Another approach: http://www.sqlfiddle.com/#!3/697d7/5
create table t(id int, name nvarchar(5), deleted bit)
insert into t(id, name, deleted) values(1, 'A1', 0)
insert into t(id, name, deleted) values(2, 'A1', 0)
insert into t(id, name, deleted) values(3, 'A1', 0)
insert into t(id, name, deleted) values(4, 'A1', 1)
insert into t(id, name, deleted) values(5, 'A2', 0)
insert into t(id, name, deleted) values(6, 'A2', 0)
with no_deletions as
(
select name
from t
group by name
having max(nullif(cast(deleted as int),0)) is null
)
select
max(id) as id,
name
from t
where name in (select name from no_deletions)
group by name
Output:
| ID | NAME |
-------------
| 6 | A2 |
Upvotes: 1
Reputation: 280252
Since you could have a third set like this:
insert into @table(id, name, deleted) values(7, 'A3', 1)
insert into @table(id, name, deleted) values(8, 'A3', 0)
I assume you want the following returned as well, since the highest id for that name was not marked as deleted:
id name
---- ----
8 A3
Then this query should do it:
;WITH x AS
(
SELECT id, name, deleted,
rn = ROW_NUMBER() OVER (PARTITION BY name ORDER BY id DESC)
FROM @table
)
SELECT id = MAX(id), name
FROM x
WHERE NOT EXISTS
(
SELECT 1 FROM x AS x2
WHERE name = x.name
AND deleted = 1 AND rn = 1
)
GROUP BY name;
If you only want rows returned where no row for a particular name was ever deleted, then it's slightly simpler:
SELECT id = MAX(id), name
FROM @table AS t
WHERE NOT EXISTS
(
SELECT 1 FROM @table
WHERE name = t.name AND deleted = 1
)
GROUP BY name;
Upvotes: 3