Lucas Arrefelt
Lucas Arrefelt

Reputation: 3929

One date check for entire query

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

Answers (2)

Hari
Hari

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

DazzaL
DazzaL

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

Related Questions