【问题标题】:Calculate median as separate column in SQL Server : error in result在 SQL Server 中将中值计算为单独的列:结果错误
【发布时间】:2016-08-04 15:07:42
【问题描述】:

我有一张表TERADATA_Q4_Temp & 添加一些过滤器后,行的外观如下:

查询:

select * 
from [TERADATA_Q4_Temp]
where CUST_ID = '100008666' and TRXN_TYPE = '2001' and MONTH = '11'

结果:

CUST_ID ACCT_NO TRXN_TYPE   CURRENCY TYPE   TRXN_DATE   MONTH   Total Amount    txn count
100008666   9335945808  2001        MXP 2015-11-17  11  5000    1
100008666   9335945808  2001        MXP 2015-11-23  11  20000   1
100008666   9335945808  2001        MXP 2015-11-09  11  5000    1

现在,我正在尝试使用以下查询计算“txn 计数”列的中位数,我得到了正确的结果:

查询:

SELECT  
    AVG(1.0E * [Total Amount]) as 'MEDIAN_DAILY_AMT'
FROM    
    (SELECT  
         [Total Amount],
         2 * ROW_NUMBER() OVER (ORDER BY [Total Amount]) - COUNT(*) OVER () AS y
     FROM   
         [TERADATA_Q4_Temp]
     WHERE
         CUST_ID = '100008666' and TRXN_TYPE = '2001' and MONTH = '11') AS d
WHERE   
    y BETWEEN 0 AND 2  

结果:

MEDIAN_DAILY_AMT
5000

但是,当我尝试将中位数计算为单独的列字段时,出现错误。你能检查我下面的查询,看看我哪里出错了-

查询:

SELECT 
    [CUST_ID], [ACCT_NO], [TRXN_TYPE], [CURRENCY TYPE], [MONTH], 
    (SELECT  
         AVG(1.0E * [Total Amount])
     FROM    
         (SELECT  
              [Total Amount],
              2 * ROW_NUMBER() OVER (ORDER BY [Total Amount]) - COUNT(*) OVER () AS y
          FROM   
              [TERADATA_Q4_Temp]) AS d
     WHERE   
         y BETWEEN 0 AND 2) as 'MEDIAN_DAILY_AMT'
FROM 
    [TERADATA_Q4_Temp]
WHERE
    CUST_ID = '100008666' and TRXN_TYPE = '2001' and MONTH = '11'
GROUP BY 
    [CUST_ID], [ACCT_NO], [TRXN_TYPE], [CURRENCY TYPE], [MONTH]

结果:

CUST_ID ACCT_NO TRXN_TYPE   CURRENCY TYPE   MONTH   MEDIAN_DAILY_AMT
100008666   9335945808  2001        MXP 11  10573.51 

你可以看到我得到的中位数是 10573.51 而不是 5000。

谢谢。

【问题讨论】:

    标签: sql sql-server median


    【解决方案1】:

    这是一个修改后的版本,可能会有所帮助。它最初用于滚动平均/中值/众数

    请注意,我添加了另一个带有一些随机余额的 ID。

    您可能还注意到,如果没有 MODE,我们会显示范围(低/高)

    对于中位数。如果有偶数个观察值,我们取中间两个的平均值。

    Declare @Table table (ID varchar(50),Measure decimal(9,2))
    Insert into @Table (ID,Measure) values
    ('100008666',5000),
    ('100008666',20000),
    ('100008666',5000),
    ('AnotherID',25000),
    ('AnotherID',1800),
    ('AnotherID',1000),
    ('AnotherID',2200)
    
    ;with cteBase as (Select *,RowNr = Row_Number() over (Partition By ID Order By Measure) From  @Table),
          cteMean as (Select ID,Mean=Avg(Measure),Rows=Count(*) From cteBase Group By ID),
          cteMedn as (Select ID,MedRow1=ceiling(Rows/2.0),MedRow2=ceiling((Rows+1)/2.0) From cteMean),
          cteMode as (Select ID,Mode=Measure,ModeHits=count(*),ModeRowNr=Row_Number() over (Partition By ID Order By Count(*) Desc) From cteBase Group By ID,Measure)
     Select A.ID
           ,MinVal  = min(Measure)
           ,MaxVal  = max(Measure)
           ,Mean    = max(B.Mean)
           ,Median  = isnull(Avg(IIF(RowNr between MedRow1 and MedRow2,Measure,null)),avg(A.Measure)) 
           ,ModeR1  = isnull(max(IIf(ModeHits>1,D.Mode,null)),min(Measure))
           ,ModeR2  = isnull(max(IIf(ModeHits>1,D.Mode,null)),max(Measure))
           ,StdDev  = Stdev(Measure)
      From  cteBase A
      Join  cteMean B on (A.ID=B.ID)
      Join  cteMedn C on (A.ID=C.ID)
      Join  cteMode D on (A.ID=D.ID and ModeRowNr=1)
      Group By A.ID
      Order By A.ID
    

    返回

    ID          MinVal  MaxVal      Mean            Median      ModeR1    ModeR2    StdDev
    100008666   5000.00 20000.00    10000.000000    5000.000000 5000.00   5000.00   8660.25403784439
    AnotherID   1000.00 25000.00    7500.000000     2000.000000 1000.00   25000.00  11677.328461596
    

    【讨论】:

    猜你喜欢
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多