Pregunta

HI all here is a MySQL problem that uses results from a 2 table join, conditionally assess them and outputs 2 values.

Here is the database structure.

The 1st table gtpro contains

a user ID (column name id)

a samples/year number ie 2, 4 or 12 times/year (column name labSamples__yr)

The 2nd table labresults contains

that same user ID (column name idgtpro)

and a date column for the sample dates (when the samples were provided) column name date

so this query returns an overview of all id's and when were the last samples submitted for that id.

SELECT a.id, a.labSamples__yr, max(b.date) as ndate from gtpro as a 
join labresults as b on a.id = b.idgtpro group by a.id

the conditions I want to evaluate looks like this.

a.labSamples__yr = 2 and ndate >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
a.labSamples__yr = 4 and ndate >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)
a.labSamples__yr = 12 and ndate >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)

So if number of samples /year is 2 and the last samle date was more than 6 months ago I want to know the id and latest date of samples for that id.

I tried using CASE and IF statements but can't quite get it right. This was my latest attempt.

select id, ndate,
case when (labSamples__yr = 2 and ndate <= DATE_SUB(CURDATE(), INTERVAL 6 MONTH))is true
then
(SELECT id from gtpro as a join labresults as b on a.id = b.idgtpro where
labSamples__yr = 2 and max(b.date) <= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)) end as id
from (SELECT a.id, a.labSamples__yr, max(b.date) as ndate from gtpro as a 
join labresults as b on a.id = b.idgtpro group by a.id) d

this tells me invalid use of group function.

Desperate for a bit of help

EDIT I messed up some of the names in the code above which i have now fixed.

¿Fue útil?

Solución

If I understand your question correctly, you should be able to put the conditions in the where clause:

SELECT a.id, a.labSamples__yr, max(b.date) as ndate
from gtpro a join
     labresults b
     on a.id = b.idgtpro
where (a.labSamples__yr = 2 and b.date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)) or
      (a.labSamples__yr = 4 and b.date >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)) or
      (a.labSamples__yr = 12 and b.date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH))
group by a.id;

That fixes your syntax problem. But, if you want the id with the maximum date, try doing this:

select a.labSamples__yr, max(b.date) as ndate,
       substring_index(group_concat(a.id order by b.date desc)) as maxid
from gtpro a join
     labresults b
     on a.id = b.idgtpro
where (a.labSamples__yr = 2 and b.date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)) or
      (a.labSamples__yr = 4 and b.date >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)) or
      (a.labSamples__yr = 12 and b.date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH))
group by a.labSamples__yr;

Putting a.id in the group by is not going to give you the maximum id of anything.

Otros consejos

Is this meant to be valid MySQL? I wasn't aware of "is true" being valid in a CASE statement. In fairness though I'm more familiar with Oracle and SQL Server but nevertheless... does any part of this statement work?

EDIT

Ok, here is what I have edited the code to be:

select id, ndate,
case when (labSamples__yr = 2 and ndate <= DATE_SUB(CURDATE(), INTERVAL 6 MONTH))
then
(SELECT id from bifipro as a join labresults as b on a.id = b.idBifipro where
labSamples__yr = 2 and max(b.date) <= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) where     a.id=d.id) end as id
from (SELECT a.id, a.labSamples__yr, max(b.date) as ndate from bifipro as a 
join labresults as b on a.id = b.idBifipro group by a.id) d
  • In your correlated subquery I have added a predicate of "where a.id = d.id"
  • I have removed the text "is true" from your case statement (this may be incorrect but I didnt' think it should be there.

The answer partly inspired by Tomas (sql clarification and syntax clarification) I got rid of the CASE all together. It seems nice and clean to me but I would like to hear any other suggestions

select id, labSamples__yr, ndate from
(SELECT a.id, a.labSamples__yr, max(b.date) as ndate from gtpro as a 
join labresults as b on a.id = b.idgtpro  group by a.id)d 
where (ndate <= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) and labSamples__yr = 2) 
or (ndate <= DATE_SUB(CURDATE(), INTERVAL 3 MONTH) and labSamples__yr = 4)
or (ndate <= DATE_SUB(CURDATE(), INTERVAL 1 MONTH) and labSamples__yr = 12)

Thanks for looking but it would still be nice to see a solution using a CASE statement for future reference???

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top