Whats, который Вы ищете, jQuery Ajax. И затем просто установите php страницу для обработки запроса.
ОБНОВЛЕНИЕ 2019: За 10 лет, прошедших с тех пор, как я написал этот ответ, было обнаружено больше решений, которые могут дать лучшие результаты. Кроме того, с тех пор выпуски SQL Server (особенно SQL 2012) представили новые функции T-SQL, которые можно использовать для вычисления медиан. В выпусках SQL Server также улучшен оптимизатор запросов, что может повлиять на производительность различных медианных решений. Net-net, мой исходный пост 2009 года все еще в порядке, но могут быть лучшие решения для современных приложений SQL Server. Взгляните на эту статью 2012 года, которая является отличным ресурсом: https://sqlperformance.com/2012/08/t-sql-queries/median
Эта статья обнаружила, что следующий шаблон очень, очень быстрее, чем все другие альтернативы, по крайней мере, на протестированной ими простой схеме. Это решение было в 373 раза быстрее (!!! ), чем самое медленное ( PERCENTILE_CONT
) протестированное решение. Обратите внимание, что для этого трюка требуются два отдельных запроса, что может оказаться практичным не во всех случаях. Также требуется SQL 2012 или новее.
DECLARE @c BIGINT = (SELECT COUNT(*) FROM dbo.EvenRows);
SELECT AVG(1.0 * val)
FROM (
SELECT val FROM dbo.EvenRows
ORDER BY val
OFFSET (@c - 1) / 2 ROWS
FETCH NEXT 1 + (1 - @c % 2) ROWS ONLY
) AS x;
Конечно, только потому, что один тест на одной схеме в 2012 году дал отличные результаты, ваш опыт может отличаться, особенно если вы используете SQL Server 2014 или более поздней версии. Если производительность важна для расчета медианы, я настоятельно рекомендую попробовать и протестировать несколько вариантов, рекомендованных в этой статье, чтобы убедиться, что вы нашли лучший вариант для своей схемы.
Я также был бы особенно осторожен при использовании (новой в SQL Server 2012) функции PERCENTILE_CONT
, рекомендованной в одном из других ответов на этот вопрос, потому что в статье, указанной выше, эта встроенная функция работает в 373 раза медленнее, чем самое быстрое решение. Возможно, что это несоответствие улучшилось за 7 лет, прошедших с тех пор, но лично я не стал бы использовать эту функцию на большой таблице, пока не проверил ее производительность по сравнению с другими решениями.
ОРИГИНАЛЬНАЯ ПИСЬМО 2009 ГОДА НИЖЕ:
Есть много способов сделать это с резко различающейся производительностью. Вот одно особенно хорошо оптимизированное решение из Медианы, ROW_NUMBER и производительности . Это особенно оптимальное решение, когда речь идет о фактических операциях ввода-вывода, генерируемых во время выполнения - оно выглядит более затратным, чем другие решения, но на самом деле намного быстрее.
Эта страница также содержит обсуждение других решений и детали тестирования производительности. Обратите внимание на использование уникального столбца в качестве средства устранения неоднозначности в случае наличия нескольких строк с одинаковым значением медианного столбца.
Как и во всех сценариях производительности базы данных, всегда пытайтесь протестировать решение с реальными данными на реальном оборудовании - вы никогда не знаешь, когда изменение оптимизатора SQL Server или особенность в вашей среде замедлит работу обычно быстрого решения.
SELECT
CustomerId,
AVG(TotalDue)
FROM
(
SELECT
CustomerId,
TotalDue,
-- SalesOrderId in the ORDER BY is a disambiguator to break ties
ROW_NUMBER() OVER (
PARTITION BY CustomerId
ORDER BY TotalDue ASC, SalesOrderId ASC) AS RowAsc,
ROW_NUMBER() OVER (
PARTITION BY CustomerId
ORDER BY TotalDue DESC, SalesOrderId DESC) AS RowDesc
FROM Sales.SalesOrderHeader SOH
) x
WHERE
RowAsc IN (RowDesc, RowDesc - 1, RowDesc + 1)
GROUP BY CustomerId
ORDER BY CustomerId;
Я хотел найти решение самостоятельно, но мой мозг споткнулся и упал на пути. Я думаю , что это работает, но не просите меня объяснять это утром. : P
DECLARE @table AS TABLE
(
Number int not null
);
insert into @table select 2;
insert into @table select 4;
insert into @table select 9;
insert into @table select 15;
insert into @table select 22;
insert into @table select 26;
insert into @table select 37;
insert into @table select 49;
DECLARE @Count AS INT
SELECT @Count = COUNT(*) FROM @table;
WITH MyResults(RowNo, Number) AS
(
SELECT RowNo, Number FROM
(SELECT ROW_NUMBER() OVER (ORDER BY Number) AS RowNo, Number FROM @table) AS Foo
)
SELECT AVG(Number) FROM MyResults WHERE RowNo = (@Count+1)/2 OR RowNo = ((@Count+1)%2) * ((@Count+2)/2)
См. Другие решения для вычисления медианы в SQL здесь: « Простой способ вычисления медианы с MySQL » (решения в основном не зависят от производителя).
В UDF напишите:
Select Top 1 medianSortColumn from Table T
Where (Select Count(*) from Table
Where MedianSortColumn <
(Select Count(*) From Table) / 2)
Order By medianSortColumn
--Create Temp Table to Store Results in
DECLARE @results AS TABLE
(
[Month] datetime not null
,[Median] int not null
);
--This variable will determine the date
DECLARE @IntDate as int
set @IntDate = -13
WHILE (@IntDate < 0)
BEGIN
--Create Temp Table
DECLARE @table AS TABLE
(
[Rank] int not null
,[Days Open] int not null
);
--Insert records into Temp Table
insert into @table
SELECT
rank() OVER (ORDER BY DATEADD(mm, DATEDIFF(mm, 0, DATEADD(ss, SVR.close_date, '1970')), 0), DATEDIFF(day,DATEADD(ss, SVR.open_date, '1970'),DATEADD(ss, SVR.close_date, '1970')),[SVR].[ref_num]) as [Rank]
,DATEDIFF(day,DATEADD(ss, SVR.open_date, '1970'),DATEADD(ss, SVR.close_date, '1970')) as [Days Open]
FROM
mdbrpt.dbo.View_Request SVR
LEFT OUTER JOIN dbo.dtv_apps_systems vapp
on SVR.category = vapp.persid
LEFT OUTER JOIN dbo.prob_ctg pctg
on SVR.category = pctg.persid
Left Outer Join [mdbrpt].[dbo].[rootcause] as [Root Cause]
on [SVR].[rootcause]=[Root Cause].[id]
Left Outer Join [mdbrpt].[dbo].[cr_stat] as [Status]
on [SVR].[status]=[Status].[code]
LEFT OUTER JOIN [mdbrpt].[dbo].[net_res] as [net]
on [net].[id]=SVR.[affected_rc]
WHERE
SVR.Type IN ('P')
AND
SVR.close_date IS NOT NULL
AND
[Status].[SYM] = 'Closed'
AND
SVR.parent is null
AND
[Root Cause].[sym] in ( 'RC - Application','RC - Hardware', 'RC - Operational', 'RC - Unknown')
AND
(
[vapp].[appl_name] in ('3PI','Billing Rpts/Files','Collabrent','Reports','STMS','STMS 2','Telco','Comergent','OOM','C3-BAU','C3-DD','DIRECTV','DIRECTV Sales','DIRECTV Self Care','Dealer Website','EI Servlet','Enterprise Integration','ET','ICAN','ODS','SB-SCM','SeeBeyond','Digital Dashboard','IVR','OMS','Order Services','Retail Services','OSCAR','SAP','CTI','RIO','RIO Call Center','RIO Field Services','FSS-RIO3','TAOS','TCS')
OR
pctg.sym in ('Systems.Release Health Dashboard.Problem','DTV QA Test.Enterprise Release.Deferred Defect Log')
AND
[Net].[nr_desc] in ('3PI','Billing Rpts/Files','Collabrent','Reports','STMS','STMS 2','Telco','Comergent','OOM','C3-BAU','C3-DD','DIRECTV','DIRECTV Sales','DIRECTV Self Care','Dealer Website','EI Servlet','Enterprise Integration','ET','ICAN','ODS','SB-SCM','SeeBeyond','Digital Dashboard','IVR','OMS','Order Services','Retail Services','OSCAR','SAP','CTI','RIO','RIO Call Center','RIO Field Services','FSS-RIO3','TAOS','TCS')
)
AND
DATEADD(mm, DATEDIFF(mm, 0, DATEADD(ss, SVR.close_date, '1970')), 0) = DATEADD(mm, DATEDIFF(mm,0,DATEADD(mm,@IntDate,getdate())), 0)
ORDER BY [Days Open]
DECLARE @Count AS INT
SELECT @Count = COUNT(*) FROM @table;
WITH MyResults(RowNo, [Days Open]) AS
(
SELECT RowNo, [Days Open] FROM
(SELECT ROW_NUMBER() OVER (ORDER BY [Days Open]) AS RowNo, [Days Open] FROM @table) AS Foo
)
insert into @results
SELECT
DATEADD(mm, DATEDIFF(mm,0,DATEADD(mm,@IntDate,getdate())), 0) as [Month]
,AVG([Days Open])as [Median] FROM MyResults WHERE RowNo = (@Count+1)/2 OR RowNo = ((@Count+1)%2) * ((@Count+2)/2)
set @IntDate = @IntDate+1
DELETE FROM @table
END
select *
from @results
order by [Month]
Если вы используете SQL 2005 или лучше, то это хороший, простой расчет медианы для одного столбца в таблице:
SELECT
(
(SELECT MAX(Score) FROM
(SELECT TOP 50 PERCENT Score FROM Posts ORDER BY Score) AS BottomHalf)
+
(SELECT MIN(Score) FROM
(SELECT TOP 50 PERCENT Score FROM Posts ORDER BY Score DESC) AS TopHalf)
) / 2 AS Median
Мой первоначальный быстрый ответ был:
select max(my_column) as [my_column], quartile
from (select my_column, ntile(4) over (order by my_column) as [quartile]
from my_table) i
--where quartile = 2
group by quartile
Это даст вам медиану и интерквартильный размах одним махом. Если вам действительно нужен только один ряд, который является медианой, то отмените предложение where.
Когда вы вставляете это в план объяснения, 60% работы приходится на сортировку данных, что неизбежно при вычислении статистики, зависящей от положения, как эта.
Я изменил ответ, чтобы следовать отличному предложению Роберта Шевчика-Робажа в комментариях ниже:
;with PartitionedData as
(select my_column, ntile(10) over (order by my_column) as [percentile]
from my_table),
MinimaAndMaxima as
(select min(my_column) as [low], max(my_column) as [high], percentile
from PartitionedData
group by percentile)
select
case
when b.percentile = 10 then cast(b.high as decimal(18,2))
else cast((a.low + b.high) as decimal(18,2)) / 2
end as [value], --b.high, a.low,
b.percentile
from MinimaAndMaxima a
join MinimaAndMaxima b on (a.percentile -1 = b.percentile) or (a.percentile = 10 and b.percentile = 10)
--where b.percentile = 5
Это должно вычислить правильные значения медианы и процентиля, когда у вас четное количество элементов данных. Опять же, откомментируйте последнее предложение where, если вам нужна только медиана, а не все перцентильное распределение.