Для медианы вы можете использовать оконную функцию PERCENTILE_CONT или PERCENTILE_DISC
(MS Sql Server 2012 +)
Пример фрагмента:
declare @Appointments table (
appt_id int primary key identity(4046100,1),
appt_date date not null default GetDate(),
account int not null,
provider_code varchar(10) not null,
office_location char(3) not null default 'REN',
appt_class char(3) not null
);
insert into @Appointments (appt_date, account, provider_code, appt_class) values
('2019-02-01',100001,'FOO1','IND'),('2019-02-01',100002,'FOO1','IND'),('2019-02-01',100002,'FOO1','PSY'),('2019-02-01',100002,'FOO1','IND'),
('2019-02-01',100002,'FOO1','IND'),('2019-02-01',100003,'FOO1','IND'),('2019-02-01',100003,'FOO1','IND'),('2019-02-01',100003,'FOO1','IND');
select provider_code, office_location, MAX(MedianContTotalAppointments) AS MedianApt
from
(
select provider_code, office_location, account
, count(appt_id) as TotalAppointments
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY count(appt_id)) OVER (PARTITION BY provider_code, office_location) AS MedianContTotalAppointments
-- , PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY count(*)) OVER (PARTITION BY provider_code, office_location) AS MedianDiscTotalAppointments
from @Appointments
where account IS NOT NULL
and appt_date BETWEEN cast('2017-02-01' as date) AND cast('2019-02-01' as date)
group by provider_code, office_location, account
) q
group by provider_code, office_location
order by provider_code, office_location;
Возвращает:
provider_code office_location MedianApt
FOO1 REN 3
В версии MS Sql Server до 2012 года этот пример фрагмента может работать:
declare @Appointments table (
appt_id int primary key identity(4046100,1),
appt_date date not null default GetDate(),
account int not null,
provider_code varchar(10) not null,
office_location char(3) not null default 'REN',
appt_class char(3) not null
);
insert into @Appointments (appt_date, account, provider_code, appt_class) values
('2019-02-01',100001,'FOO1','IND'),('2019-02-01',100002,'FOO1','IND'),('2019-02-01',100002,'FOO1','PSY'),('2019-02-01',100002,'FOO1','IND')
,('2019-02-01',100002,'FOO1','IND'),('2019-02-01',100003,'FOO1','IND'),('2019-02-01',100003,'FOO1','IND'),('2019-02-01',100003,'FOO1','IND')
--,('2019-02-01',100004,'FOO1','IND'),('2019-02-01',100004,'FOO1','IND')
;
select provider_code, office_location, AVG(TotalAppointments) AS MedianApt
from
(
select provider_code, office_location, account
, COUNT(appt_id) as TotalAppointments
, ROW_NUMBER() OVER (PARTITION BY provider_code, office_location ORDER BY COUNT(appt_id) ASC) AS rn
, COUNT(*) OVER (PARTITION BY provider_code, office_location) AS cnt
from @Appointments
where account IS NOT NULL
and appt_date BETWEEN cast('2017-02-01' as date) AND cast('2019-02-01' as date)
group by provider_code, office_location, account
) q
where rn in (FLOOR((cnt+1)*0.5), CEILING((cnt+1)*0.5))
group by provider_code, office_location
order by provider_code, office_location;