views:

56

answers:

3

Hello,

I'm running requests on an Oracle database. One of my tables contains time slots for Elements and there can be several time slots for the same Element so that the following example is correct :

ID    ELEMENT_ID    BEGIN_DATE    END_DATE
--------------------------------------------
1     1             01/01/2007    01/06/2007
2     1             01/06/2007   

3     2             01/01/2006    01/07/2006
4     2             01/07/2006    31/12/2006

The time slot for which END_DATE is not filled means that it is still running (so, this is the most recent time slot for the Element).

Thus, when I search the most recent END_DATE for each Element, I want to obtain the rows #2 and #4. So, The problem I'm facing is to consider NULL as the highest END_DATE ...

Is it possible to do this in one single SQL request ?

Of course I tried a simple :

SELECT MAX(END_DATE) FROM ...

but it's not enought because of the NULL values.

Thanks in advance.

+6  A: 

Change the null values to some future value

SELECT MAX(NVL(END_DATE,SYSDATE + 1) ...
LesterDove
This assumes that none of your end_dates are in the future, which seems to be the case based on your example.
LesterDove
This is the case, none of my end_dates are in the future. Thanks for the snippet, it works fine !! However, I'm still having a last little problem because my next step is to select the whole row for the identified MAX(END_DATE) ... so inserting a fake date in `END_DATE` isn't compatible anymore with any thing like `SELECT * FROM MyTable WHERE END_DATE = (SELECT MAX(...));` Any last tip for me ?? :)
Clem
Technically, your approach would work, as long as you compare apples to apples and replace the nulls on both sides of the comparison: SELECT * FROM MyTable WHERE NVL(END_DATE,SYSDATE + 1) = (SELECT MAX(...));There are probably a number of other ways ...
LesterDove
Yes ! I did it exactly this way ! Thanks a lot !
Clem
+3  A: 

Try:

select element_id, max(coalesce(end_date, date '4000-12-31')) as max_end_date
from ...
Tony Andrews
+2  A: 

Use an ORDER BY with NULLS FIRST, e.g.:

SELECT DISTINCT
       FIRST_VALUE(id)
       OVER (PARTITION BY element_id
             ORDER BY end_date DESC NULLS FIRST) latest_id,
       element_id,
       FIRST_VALUE(begin_date)
       OVER (PARTITION BY element_id
             ORDER BY end_date DESC NULLS FIRST) latest_id,
       FIRST_VALUE(end_date)
       OVER (PARTITION BY element_id
             ORDER BY end_date DESC NULLS FIRST) latest_id
FROM   ...


ID    ELEMENT_ID    BEGIN_DATE    END_DATE
--------------------------------------------
2     1             01/06/2007   
4     2             01/07/2006    31/12/2006
Jeffrey Kemp
Great solution too ! I coded the previous one but keep your method in mind for the next time ! Thanks.
Clem