HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

Calculating Median Value within a Group By

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
groupvaluewithincalculatingmedian

Problem

I have a Stored Procedure which calculates the Mean duration of a request / response cycle within 10 minute intervals. This works well and suits my needs for plotting charts. What I would like to do next is calculate the Median value... I suspect I would need a subquery but can't figure out how to accomplish this.

SELECT dateadd(minute, 10 + (datediff(minute, 0, [Started]) / 10) * 10, 0) AS [Time]
     ,AVG(CASE WHEN Duration is null OR Duration = 0 
              THEN null ELSE Duration 
          END) AS [Mean Response Time]
FROM [Application].[Exchange] WITH (NOLOCK)
WHERE [Started] >= '24 Oct 2012' AND [Started] < '25 Oct 2012'
GROUP BY dateadd(minute, 10 + (datediff(minute, 0, [Started]) / 10) * 10, 0) 
ORDER BY dateadd(minute, 10 + (datediff(minute, 0, [Started]) / 10) * 10, 0)


Can anyone suggest a way I might accomplish this?

Solution

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- replace WITH (nolock)

SELECT [Time]
       ,AVG(NULLIF(Duration,0)) AS [Mean Response Time]
       ,AVG(CASE WHEN Rn in (Round(CN/2.0,0),Round((CN+1)/2.0,0))
                 THEN Duration END) [Median]
FROM
(
  SELECT [Time], Duration,
         Rn = Row_Number() over (partition by CASE WHEN NullIf(Duration,0) is null then 1 else 2 end,
                                         Time
                                 order by Duration),
         Cn = Count(1) over (partition by CASE WHEN NullIf(Duration,0) is null then 1 else 2 end,
                                         Time)
  FROM (
    SELECT dateadd(minute, 10 + (datediff(minute, 0, [Started]) / 10) * 10, 0) AS [Time],
           Duration
    FROM [Application].[Exchange]
    WHERE [Started] >= '20121024' AND [Started] < '20121025'
  ) X
) Y
GROUP BY [Time]
ORDER BY [Time];

Code Snippets

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- replace WITH (nolock)

SELECT [Time]
       ,AVG(NULLIF(Duration,0)) AS [Mean Response Time]
       ,AVG(CASE WHEN Rn in (Round(CN/2.0,0),Round((CN+1)/2.0,0))
                 THEN Duration END) [Median]
FROM
(
  SELECT [Time], Duration,
         Rn = Row_Number() over (partition by CASE WHEN NullIf(Duration,0) is null then 1 else 2 end,
                                         Time
                                 order by Duration),
         Cn = Count(1) over (partition by CASE WHEN NullIf(Duration,0) is null then 1 else 2 end,
                                         Time)
  FROM (
    SELECT dateadd(minute, 10 + (datediff(minute, 0, [Started]) / 10) * 10, 0) AS [Time],
           Duration
    FROM [Application].[Exchange]
    WHERE [Started] >= '20121024' AND [Started] < '20121025'
  ) X
) Y
GROUP BY [Time]
ORDER BY [Time];

Context

StackExchange Database Administrators Q#27599, answer score: 5

Revisions (0)

No revisions yet.