在Sql Server中查找中位数

时间:2017-11-16 23:39:46

标签: sql sql-server

我想从Microsoft SQL Server Management Studio中的[dbo]。[ReplaceCost_DirectCost_Details]视图中获取unitRate的中位数。我已经得到了Min,Max和平均值。但是我不知道中位数。我尝试了以下代码,但未获得中位数。谢谢你的帮助。

 select 
        JobName as JobName
       ,Client as Client
       ,AssetClass as AssetClass
       ,AssetType as AssetType
       ,AssetSubType as AssetSubType
       ,Component as Component
       ,ComponentType as ComponentType
       ,ComponentSubType as ComponentSubType
       ,UnitRate AS UnitRate
       ,Max(UnitRate) over (partition by JobName,Client,AssetClass,AssetType,AssetSubType,Component,ComponentType,ComponentSubType) as [MaxFinalUnitRate]
       ,Min(UnitRate) over (partition by JobName,Client,AssetClass,AssetType,AssetSubType,Component,ComponentType,ComponentSubType)  as [MinFinalUnitRate]
       ,AVG(UnitRate) over (partition by JobName,Client,AssetClass,AssetType,AssetSubType,Component,ComponentType,ComponentSubType) as [MeanFinalUnitRate]
       ,AVG (UnitRate)  over (partition by JobName,Client,AssetClass,AssetType,AssetSubType,Component,ComponentType,ComponentSubType)as Median
       from
        (
         Select top (10)
        JobName as JobName
       ,Client as Client
       ,AssetClass as AssetClass
       ,AssetType as AssetType
       ,AssetSubType as AssetSubType
       ,Component as Component
       ,ComponentType as ComponentType
       ,ComponentSubType as ComponentSubType
       ,UnitRate AS UnitRate
       ,ROW_NUMBER () over (partition by JobName,Client,AssetClass,AssetType,AssetSubType,Component,ComponentType,ComponentSubType order by UnitRate) as [RowNum]
       ,COUNT(*) OVER (PARTITION BY JobName,Client,AssetClass,AssetType,AssetSubType,Component,ComponentType,ComponentSubType ) AS RowCnt

     from [dbo].[ReplaceCost_DirectCost_Details] rdd
     where  client = 'APV_Ballina_Shire_Council_Old'  and  UnitRate is not Null and UnitRate <> 0 
       ) x
       WHERE   RowNum IN ((RowCnt + 1) / 2, (RowCnt + 2) / 2) 

2 个答案:

答案 0 :(得分:0)

修改

SQL Fiddle

CREATE TABLE Table1
    ([somevalue] int)
;

INSERT INTO Table1
    ([somevalue])
VALUES
    (141),
    (325),
    (325),
    (353),
    (3166),
    (325),
    (207),
    (141),
    (3166),
    (161)
;

查询1

with cte as (
  select *
  , row_number() over(order by somevalue) as RowNum
  , count(*) over() as RowCnt
  from table1
  )
select
*
from CTE
WHERE   RowNum IN ((RowCnt + 1) / 2, (RowCnt + 2) / 2) 

| somevalue | RowNum | RowCnt |
|-----------|--------|--------|
|       325 |      5 |     10 |
|       325 |      6 |     10 |

请考虑以下小例子。有7行数据,中位数是&#34;中点&#34;其中,where子句使用与行计数相比的行号,并返回该中点值。该值(67)重复了该小样本的中位数。

SQL Fiddle

MS SQL Server 2014架构设置

CREATE TABLE Table1
    ([somevalue] int)
;

INSERT INTO Table1
    ([somevalue])
VALUES
    (2),
    (45),
    (67),
    (89),
    (4567),
    (6),
    (1290)
;

查询1

with cte as (
  select *
  , row_number() over(order by somevalue) as RowNum
  , count(*) over() as RowCnt
  from table1
  )
select
*
from CTE
WHERE   RowNum IN ((RowCnt + 1) / 2, (RowCnt + 2) / 2) 

<强> Results

| somevalue | RowNum | RowCnt |
|-----------|--------|--------|
|        67 |      4 |      7 |

答案 1 :(得分:0)

(很抱歉使用了第二个答案,但如果只是添加到前一个答案就会丢失)

我真的不确定查询的预期输出是什么。但我注意到您使用的是TOP(10),为此,必须按进行订购,否则结果对前10行不确定。

虽然以下内容可能会产生超出您需要的行数,但这可能有助于找到解决方案。

WITH Basis as (
      SELECT
            JobName
          , Client
          , AssetClass
          , AssetType
          , AssetSubType
          , Component
          , ComponentType
          , ComponentSubType
          , UnitRate
          , ROW_NUMBER() OVER (PARTITION BY JobName, Client, AssetClass, AssetType, AssetSubType, Component, ComponentType, ComponentSubType
                               ORDER BY UnitRate)
            AS [rownum]
      FROM [dbo].[ReplaceCost_DirectCost_Details] rdd
      WHERE client = 'APV_Ballina_Shire_Council_Old'
      AND UnitRate IS NOT NULL
      AND UnitRate <> 0
     )
, Top10s as (
      SELECT
            JobName
          , Client
          , AssetClass
          , AssetType
          , AssetSubType
          , Component
          , ComponentType
          , ComponentSubType
          , UnitRate
          , rownum
          , COUNT(*) OVER (PARTITION BY JobName, Client, AssetClass, AssetType, AssetSubType, Component, ComponentType, ComponentSubType)
            AS rowcnt
      FROM Basis
      WHERE rownum <= 10
      )
, Medians as (
      SELECT
            JobName
          , Client
          , AssetClass
          , AssetType
          , AssetSubType
          , Component
          , ComponentType
          , ComponentSubType
          , AVG(UnitRate) AS Median
      FROM Top10s
      WHERE RowNum IN ((RowCnt + 1) / 2, (RowCnt + 2) / 2)
      GROUP BY
            JobName
          , Client
          , AssetClass
          , AssetType
          , AssetSubType
          , Component
          , ComponentType
          , ComponentSubType
          , AVG(UnitRate) 
      )
SELECT
      JobName
    , Client
    , AssetClass
    , AssetType
    , AssetSubType
    , Component
    , ComponentType
    , ComponentSubType
    , UnitRate
    , rownum
    , rowcnt
    , MAX(UnitRate) OVER (PARTITION BY JobName, Client, AssetClass, AssetType, AssetSubType, Component, ComponentType, ComponentSubType) AS [maxfinalunitrate]
    , MIN(UnitRate) OVER (PARTITION BY JobName, Client, AssetClass, AssetType, AssetSubType, Component, ComponentType, ComponentSubType) AS [minfinalunitrate]
    , AVG(UnitRate) OVER (PARTITION BY JobName, Client, AssetClass, AssetType, AssetSubType, Component, ComponentType, ComponentSubType) AS [meanfinalunitrate]
    , Medians.Median
FROM Top10s t
JOIN Medians m ON t.JobName = m.JobName
    AND t.Client = m.Client
    AND t.AssetClass = m.AssetClass
    AND t.AssetType = m.AssetType
    AND t.AssetSubType = m.AssetSubType
    AND t.Component = m.Component
    AND t.ComponentType = m.ComponentType
    AND t.ComponentSubType = m.ComponentSubType
;