Reputation: 45
I have a database that's used to keep a history of the registers that are open and closed
id | name | assigned_to | state | created_on | created_by
---------------------------------------------------------
1 | Jay | 1 | OPEN | 01/01/2011 | 1
2 | Kay | 2 | OPEN | 01/01/2011 | 1
3 | Jay | 1 | CLOSED| 01/01/2111 | 1
"assigned_to" is the employee's id. "name" is the name of the register that they used.
What the database is saying is that "Jay" has been open and closed but "Kay" is not closed at all. I can't figure out a cleaver way to determine how to get only the register that is currently open. Any ideas on how to approach this? Keep in mind that there will be thousands of these as time progresses.
Upvotes: 0
Views: 43
Reputation: 180917
You can simply use ROW_NUMBER()
to get the latest value per name, and list those with the latest state equal to OPEN
;
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY name ORDER BY created_on DESC, id DESC) rn
FROM myTable
)
SELECT id, name, assigned_to, state, created_on, created_by
FROM cte WHERE rn=1 AND state='OPEN';
Upvotes: 0
Reputation: 6827
This will produce the rows with the latest created_on (by name) only if it has a state of "CLOSED".
select
*
from
regs a
join (select name,max(created_on) created_on
from regs
group by name) b
on a.name = b.name
where
a.created_on = b.created_on
and state = 'CLOSED'
Upvotes: 0
Reputation: 1269743
Making a few assumptions, you can solve this as a "set-within-sets" subquery. The major assumption is that a name
is "closed" only once and is not opened again afterwards. The following query checks that there is no closed
state:
select r.name
from registers r
group by r.name
having sum(case when state = 'Closed' then 1 else 0 end) = 0;
If a name
can be opened after being closed, then you want to check the most recent time of each. You can try this:
select r.name
from registers r
group by r.name
having sum(case when state = 'Closed' then 1 else 0 end) = 0 or
max(case when state = 'Closed' then id end) > max(case when state = 'Opened' then id end);
Upvotes: 2