Reputation: 3929
I have the following query:
select
fp.id,
fr.id,
sum(case
when to_date(fp.offered_date) BETWEEN TO_DATE( :ad_startdate, 'YYYY-MM-DD')
AND TO_DATE(:ad_enddate, 'YYYY-MM-DD') and fp.result <> 'E'
then 1
else 0
end) total,
sum(case when fp.result = 'G'
and to_date(fp.offered_date) >= :ad_startdate
and to_date(fp.offered_date) <= :ad_enddate then 1 else 0 end) colorgreen,
sum(case when fp.resultat = 'R'
and to_date(fp.offered_date) >= :ad_startdate
and to_date(fp.offered_date) <= :ad_enddate then 1 else 0 end) colorred
FROM
fruit_properties fp, fruit fr
WHERE
fp.id = fr.id
GROUP BY
fp.id, fr.id
I'm checking dates 1 time for each sum column and have a feeling this can be made once somehow? Right now if I check only once at the total column, then colorgreen + colorred might be larger than the total since it counts no matter what date they have.
Can my query be enhanced somehow?
Upvotes: 1
Views: 74
Reputation: 4612
You can put the date check in the where clause:
select
fp.id,
fr.id,
sum(case when and fp.result <> 'E' then 1 else 0 end) total,
sum(case when fp.result = 'G' then 1 else 0 end) colorgreen,
sum(case when fp.resultat = 'R' then 1 else 0 end) colorred
FROM
fruit_properties fp, fruit fr
WHERE
fp.id = fr.id
AND to_date(fp.offered_date) >= :ad_startdate
AND to_date(fp.offered_date) <= :ad_enddate
GROUP BY
fp.id, fr.id
Edit: as pointed out in the comments, this query will filter out ids which doesn't have any offer dates in the given interval.
Upvotes: 1
Reputation: 21973
you can simplify like this. but PLEASE check your SQL. you're mixing TO_DATE and CHAR datatypes. this will only end in disaster.
eg you have:
when to_date(fp.offered_date) BETWEEN TO_DATE( :ad_startdate, 'YYYY-MM-DD')
AND TO_DATE(:ad_enddate, 'YYYY-MM-DD')
vs
sum(case when fp.result = 'G'
and to_date(fp.offered_date) >= :ad_startdate
in one case you are TO_DATE'ing ad_startdate but not another (so is it a date already or not?). you are also TO_DATEing the column but crucially WITHOUT a format mask. is the column really a VARCHAR datatype? if so you really should not store dates as anything but DATEs.
anyway assuming the column is a DATE datatype and the binds are of type DATE..
select fruit_prop_Id,fruit_id,
sum(case when result != 'E' then within_offer else 0 end) total,
sum(case when result = 'R' then within_offer else 0 end) colorred,
sum(case when result = 'G' then within_offer else 0 end) colorgreen
from (select fp.id fruit_id,
fr.id fruit_prop_Id,
fp.result,
case
when fp.offered_date >= :ad_startdate
and fp.offered_date <= :ad_enddate then 1 else 0 end within_offer
from fruit_properties fp, fruit fr
where fp.id = fr.id)
group by fruit_id, fruit_prop_Id
Upvotes: 2