Reputation: 124656
Given this example data set:
-----------------------------
| item | date | val |
-----------------------------
| apple | 2012-01-11 | 15 |
| apple | 2012-02-12 | 19 |
| apple | 2012-03-13 | 7 |
| apple | 2012-04-14 | 6 |
| orange | 2012-01-11 | 15 |
| orange | 2012-02-12 | 8 |
| orange | 2012-03-13 | 11 |
| orange | 2012-04-14 | 9 |
| peach | 2012-03-13 | 5 |
| peach | 2012-04-14 | 15 |
-----------------------------
I'm looking for the query that for each item, it will select the first date where the val went below CONST=10 without coming back above afterwards. In this example that would be:
-----------------------------
| item | date | val |
-----------------------------
| apple | 2012-03-13 | 7 |
| orange | 2012-04-14 | 9 |
-----------------------------
Is this even possible without using cursors? I'm looking for this in Sybase.
If this is not possible without cursors, I can process the records in a programming language. In that case however, since in my real use case the full history is very long, I need a "suitable" query that selects just "enough" records for computing the record I am ultimately after: the most recent record where val dipped below CONST without coming back above it.
Upvotes: 2
Views: 1240
Reputation: 44326
For MySql:
select t.item, t.date1, t.val
from
(
select min(date) date1, item from tablename t
where not exists (select 1 from tablename where item = t.item
and date1 > t.date1 and val >= 10)
and val < 10
group by item
) a
inner join
@t t
on a.item = t.item and a.date1 = t.date1
For different databases such as MS-sql 2005+:
select item, date, val from
(
select *, row_number() over (partition by item order by date) rn
from tablename t
where not exists (select 1 from @t where item = t.item and
date > t.date and val >= 10)
and val < 10
) a where rn = 1
Upvotes: 1
Reputation: 51494
This returns the result set as detailed.
select tablename.* from tablename
inner join
(
select tablename.item, min(tablename.[date]) as mindate
from tablename
inner join (
select
item,
max([date]) lastoverdate
from tablename
where val>@const
group by item
) lastover
on tablename.item = lastover.item
and tablename.[date]> lastoverdate
group by tablename.item
) below
on tablename.item = below.item
and tablename.date = below.mindate
Upvotes: 3