Reputation: 4976
I've got a simple temporal table that looks like this:
Table: item_approval
item user status modified
2 fred approved 2010-12-01 00:00:00
3 fred approved 2010-12-02 00:00:00
4 fred disapproved 2010-12-03 00:00:00
7 jack unapproved 2010-12-05 00:00:00
4 fred approved 2010-12-06 00:00:00
4 jack unapproved 2010-12-07 00:00:00
4 fred disapproved 2010-12-04 00:00:00
I'm using DBIx::Class. My "Item" result is defined with:
__PACKAGE__->has_many(
"item_approvals",
"Schema::Result::ItemApproval",
{ "foreign.item" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
Which means I can do:
my $item = $schema->resultset('Item')->find({id=>4});
Which is fine. Then, I can do:
my @approvals = $item->item_approvals;
to get a resultset like this:
item user status modified
4 fred disapproved 2010-12-03 00:00:00
4 fred approved 2010-12-06 00:00:00
4 jack unapproved 2010-12-07 00:00:00
4 fred disapproved 2010-12-04 00:00:00
My question: How do I get the set of Fred and Jack's single most recent approval status? That is, I want to get this resultset:
item user status modified
4 fred approved 2010-12-06 00:00:00
4 jack unapproved 2010-12-07 00:00:00
I tried things like this:
my @approvals = $item->search({}, {
group_by => 'user',
order_by => {-desc => 'modified'}
});
but the "ORDER BY" is executed after the "GROUP BY", so I get things like this instead:
item user status modified
4 fred disapproved 2010-12-03 00:00:00
4 jack unapproved 2010-12-07 00:00:00
Help?
Upvotes: 0
Views: 722
Reputation: 3635
From the behavior described in your comments I'm guessing your database is MySQL.
I'm also assuming your item_approval
table has a primary key which I will call PK
.
One option is to use a sub select to pick the row that has the largest (most recent) modified
value:
select item, user, status, modified
from item_approval me
where PK = (select s.PK from item_approval s where me.item = s.item and me.user = s.user order by s.modified desc, s.PK desc limit 1)
and me.item = 4
This is a fairly slow option because it will re-run the sub select for each row and then reject all but one row for each item/user combination. Other databases have slightly different ways to get similar results.
Upvotes: 1