Question

I want to return in the same row the results of a particular measure on different time range. For instance "Last 30 days", "Last 7 days", "Last 3 days". On doing that I've initially used the UNION function, and created multiple sub-queries for every time range. The downside of doing that is I'm collecting the same numbers three times, with a consequent increase in running time.

A colleague suggested me to use the CASE function to segment the time range. I've initially thought to implement it as follows:

select tp.Name, 
    case when pub.Date between DATEADD(day, -31, getdate()) and DATEADD(day, -1, getdate()) 
        then SUM(Impressions) else 0 end 'Last 30 days Impressions',
    case when pub.Date between DATEADD(day, -31, getdate()) and DATEADD(day, -1, getdate()) 
        then SUM(Revenue * rler.Rate) else 0 end 'Last 30 days Revenues',
    case when pub.Date between DATEADD(day, -8, getdate()) and DATEADD(day, -1, getdate()) 
        then SUM(Impressions) else 0 end 'Last 7 days Impressions',
    case when pub.Date between DATEADD(day, -8, getdate()) and DATEADD(day, -1, getdate()) 
        then SUM(Revenue * rler.Rate) else 0 end 'Last 7 days Revenues',
    case when pub.Date between DATEADD(day, -4, getdate()) and DATEADD(day, -1, getdate()) 
        then SUM(Impressions) else 0 end 'Last 3 days Impressions',
    case when pub.Date between DATEADD(day, -4, getdate()) and DATEADD(day, -1, getdate()) 
        then SUM(Revenue * rler.Rate) else 0 end 'Last 3 days Revenues'

from ...

where ...

group by tp.Name, tp.Kind, pub.Date

order by 'Last 30 days Impressions'

Unfortunately this will return a row for each Name, Kind and Date which is not what I want. The issue I think relies on the pub.Date in the GROUP BY call. What should I do to overcome the issue?

Was it helpful?

Solution 2

I'm answering my own question. The result can be achieve using the following code:

select tp.Name, 
    sum(case when pub.Date between DATEADD(day, -31, getdate()) and DATEADD(day, -1, getdate()) 
        then Impressions else 0 end) 'Last 30 days Impressions',
    sum(case when pub.Date between DATEADD(day, -31, getdate()) and DATEADD(day, -1, getdate()) 
        then (Revenue * rler.Rate) else 0 end) 'Last 30 days Revenues',
    sum(case when pub.Date between DATEADD(day, -8, getdate()) and DATEADD(day, -1, getdate()) 
        then Impressions else 0 end) 'Last 7 days Impressions',
    sum(case when pub.Date between DATEADD(day, -8, getdate()) and DATEADD(day, -1, getdate()) 
        then (Revenue * rler.Rate) else 0 end) 'Last 7 days Revenues',
    sum(case when pub.Date between DATEADD(day, -4, getdate()) and DATEADD(day, -1, getdate()) 
        then Impressions else 0 end) 'Last 3 days Impressions',
    sum(case when pub.Date between DATEADD(day, -4, getdate()) and DATEADD(day, -1, getdate()) 
        then (Revenue * rler.Rate) else 0 end) 'Last 3 days Revenues'

from ...

where ...

group by tp.Name, tp.Kind

order by 'Last 30 days Impressions' desc

OTHER TIPS

You can't quite implement your colleague's suggestion because the times overlap. You can do non-overlapping ranges, something like this:

select tp.Name, 
        (case when pub.Date between DATEADD(day, -3, getdate()) and DATEADD(day, -1, getdate()) 
              then 'Last 3 days Impressions'
              when pub.Date between DATEADD(day, -7, getdate()) and DATEADD(day, -1, getdate()) 
              then '4-7 days Impressions'
              when pub.Date between DATEADD(day, -31, getdate()) and DATEADD(day, -1, getdate()) 
              then '8-31 days Impressions'
              else 'Older'
         end) as TimeRange,
       SUM(Impressions) as NumImpressions,
       . . . 
from . . .
where . . .
group by tp.Name, 
         (case when pub.Date between DATEADD(day, -3, getdate()) and DATEADD(day, -1, getdate()) 
               then 'Last 3 days Impressions'
               when pub.Date between DATEADD(day, -7, getdate()) and DATEADD(day, -1, getdate()) 
               then '4-7 days Impressions'
               when pub.Date between DATEADD(day, -31, getdate()) and DATEADD(day, -1, getdate()) 
               then '8-31 days Impressions'
               else 'Older'
          end)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top