Question

I have the following sample table called 'timtest':

itemcode     qty_available  date
apple        0              1/23/2014
apple        96             1/27/2014
apple        136            2/15/2014
orange       12             1/23/2014
orange       48             2/5/2014
peach        0              1/23/2014
peach        300            2/5/2014
peach        315            2/10/2014
peach        330            2/15/2014
banana       0              1/23/2014
pineapple    24             1/23/2014

I only want one instance of each unique value in only the itemcode column. Criteria for selecting which row to select for each unique itemcode is based on the qty being greater than zero and the soonest date any qty greater than zero is available. if there is a qty greater than zero available today, I'd like to return that row. If the qty available on today's date is 0, I want to find the next available record in the nearest future where there is any qty greater than zero and return that row. If there is a qty of zero today and there is no other future date, I'd like to return the row that shows zero. This table will never have a date in the past, and all records will have an entry with today's date.

Here is the desired result set from the above sample data, considering today is 1/23/2014:

itemcode    qty_available   date
apple       96              1/27/2014
orange      12              1/23/2014
peach       300             2/5/2014
banana      0               1/23/2014
pineapple   24              1/23/2014

Can you help me with the correct query?

Was it helpful?

Solution

I think this is the logic that you want to get the date:

select itemcode,
       coalesce(min(case when qty_available > 0 then date end), min(date)) as thedate
from timtest tt
where date >= date(now())
group by itemcode;

The expression coalesce(min(case when qty > 0 then date end), min(date)) seems to encapsulate your logic. The first part of the coalesce returns the first date when qty > 0. If none of these exist, then it finds the first date with 0. You don't state what to do when there is no record for today, but there is a record in the future for 0. This returns the first such record.

To get the quantity, let's join back to this:

select tt.*
from timtest tt join
     (select itemcode,
             coalesce(min(case when qty_available > 0 then date end), min(date)) as thedate
      from timtest tt
      where date >= date(now())
      group by itemcode
     ) id
     on tt.itemcode = id.itemcode and tt.date = id.thedate;

EDIT:

No accounting for bad date formats. Here is a version for this situation:

select tt.*
from timtest tt join
     (select itemcode,
             coalesce(min(case when qty_available > 0 then thedate end), min(thedate)) as thedate
      from (select tt.*, str_to_date(date, '%m/%d/%Y') as thedate
            from timtest tt
           ) tt
      where thedate >= date(now())
      group by itemcode
     ) id
     on tt.itemcode = id.itemcode and str_to_date(tt.date, '%m/%d/%Y') = id.thedate;

Advice for the future: store dates in the database as a date/datetime data time and not as strings. If you have store store them as strings, use the YYYY-MM-DD format, because you can use comparisons and order by.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top