Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 Median DateTime?

Author  Topic 

MarcH
Starting Member

2 Posts

Posted - 2007-07-11 : 12:01:36
Hi,

I'm trying to work out the median date for a "datetime" field.

Below is the SQL I'm using, but this is returning "The row in the middle" as opposed to the calculated median value.

Any ideas?


select cast(avg(cast(datetime_field as numeric)) as datetime)
from (
select datetime_field,
count(*)over( ) total,
cast(count(*)over( ) as numeric)/2 mid,
ceiling(cast(count(*)over( ) as numeric)/2) next,
row_number()over( order by datetime_field) rn
from table
where datetime_field is not null
) x
where( total%2 = 0
and rn in ( mid, mid+1 )
)
or ( total%2 = 1
and rn = next
)

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2007-07-11 : 12:13:52
It would be better if you started with an explanation of exactly what you are are trying to do. Some sample data and expected results would be helpful also:
Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Also, the code you posted appears to be SQL 2005, but you posted on the Transact-SQL (2000) forum. Which are you using?



CODO ERGO SUM
Go to Top of Page

MarcH
Starting Member

2 Posts

Posted - 2007-07-11 : 12:48:50
Thanks for the prompt reply!

Fortuntly in gathering the data needed to show the problem, the answer presented itself and has now been corrected (ordered by the wrong field ).

FWIW: To calculate the Median date for a set of values in SQL 2005, use the SQL below :


select cast(avg(cast(<FIELD_NAME> as float)) as datetime)
from (
select <FIELD_NAME>,
count(*)over( ) total,
cast(count(*)over( ) as float)/2 mid,
ceiling(cast(count(*)over( ) as float)/2) next,
row_number()over( order by <FIELD_NAME>) rn
from <TABLE_NAME>
where <FIELD_NAME> is not null
) x
where( total%2 = 0
and rn in ( mid, mid+1 )
)
or ( total%2 = 1
and rn = next
)



Marc.

quote:
Originally posted by Michael Valentine Jones

It would be better if you started with an explanation of exactly what you are are trying to do. Some sample data and expected results would be helpful also:
Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx


Also, the code you posted appears to be SQL 2005, but you posted on the Transact-SQL (2000) forum. Which are you using?



CODO ERGO SUM

Go to Top of Page

mattyblah
Starting Member

49 Posts

Posted - 2007-07-13 : 09:46:47
Does this help? It's calculating the median of an int field, but can be easily used for datetime fields.


declare @t table(
val int
);

insert into @t values (1);
insert into @t values (1);
insert into @t values (1);
insert into @t values (2);
insert into @t values (3);
insert into @t values (4);
insert into @t values (5);
insert into @t values (6);
insert into @t values (7);

select avg(1. * val) as median from
(select row_number() over (order by val asc) as sort_asc
, row_number() over (order by val desc) as sort_desc
, val
from @t) t
where abs(sort_asc - sort_desc) <= 1


This is also in 2005, which it appears you are using with the row_number() function in the first post.
Go to Top of Page

Jeff Moden
Aged Yak Warrior

652 Posts

Posted - 2007-07-15 : 13:54:38
Ummm... Median IS the "row in the middle"... are you looking for "Average" instead?

--Jeff Moden
Go to Top of Page

jsmith8858
Dr. Cross Join

7423 Posts

Posted - 2007-07-15 : 14:07:13
quote:
Originally posted by Jeff Moden

Ummm... Median IS the "row in the middle"... are you looking for "Average" instead?

--Jeff Moden



There are different types of medians, but typically it is the row in the middle for an odd number of rows, or the average of the two middlest rows for an even number of rows. Since the average of one value is that value, avg() works for both situations as long as you get the row(s) you need to use.

- Jeff
http://weblogs.sqlteam.com/JeffS
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2007-07-15 : 16:18:21
Think about it
asc desc diff 
1 4 3 -- even number of datapoints
2 3 1
3 2 -1
4 1 -3

1 3 2 -- odd number of datapoints
2 2 0
3 1 -2

select avg(val) as median from
(select row_number() over (order by val asc) as sort_asc
, row_number() over (order by val desc) as sort_desc
, val
from table1) as t
where sort_asc - sort_desc between -1 and 1

Peter Larsson
Helsingborg, Sweden
Go to Top of Page

Jeff Moden
Aged Yak Warrior

652 Posts

Posted - 2007-07-15 : 18:26:30
I was referring to the OP who stated "but this is returning "The row in the middle" as opposed to the calculated median value"...

--Jeff Moden
Go to Top of Page
   

- Advertisement -