문제

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?

도움이 되었습니까?

해결책 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

다른 팁

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)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top