在Sql上计算中位数

时间:2011-06-02 11:00:24

标签: sql-server

我对SQL很新。我试图使用下面的代码,它不断给我以下错误 -

  

Msg ORDER BY子句无效   视图,内联函数,派生   表,子查询和公用表   表达式,除非TOP或FOR XML   也指明了。

     

'2'附近的语法不正确。

请有人帮忙 - 我哪里错了?

我只是想计算中位数。

有人可以建议修改此代码,因为我已经找到了别人的工作。

非常感谢任何帮助。

SELECT
    TOP (100) PERCENT Name, Sales Median
FROM
    (SELECT 
         a1.Name, a1.Sales, COUNT(a1.Sales) Rank
     FROM          
         PSE.vw_EM_Data a1, PSE.vw_EM_Data a2
     WHERE      
         a1.Sales < a2.Sales OR
         (a1.Sales = a2.Sales AND a1.Name <= a2.Name)
     GROUP BY 
         a1.Name, a1.Sales
     ORDER BY 
         a1.Sales DESC) a3
WHERE 
    Rank = (SELECT (COUNT(*) + 1) DIV 2 FROM Total_Sales);
WHERE     
    (Name LIKE 'John%') 
    AND (DISPOSAL = '1') 
    AND (DATE BETWEEN CONVERT(DATETIME, '2010-04-01 00:00:00', 102) AND CONVERT(DATETIME, '2011-03-30 00:00:00', 102))

2 个答案:

答案 0 :(得分:2)

您的问题来自子选择a3

中的顺序

为什么不考虑使用Ranking Functions (Transact-SQL)

答案 1 :(得分:0)

要指出一些事情:

1)我永远不会使用您在内部SELECT中使用的“旧式”JOIN语法 - 它很容易导致不需要的笛卡尔产品 - 就像你的情况一样(尽管我不是确定是否需要......)

所以而不是:

FROM          
   PSE.vw_EM_Data a1, PSE.vw_EM_Data a2

我建议使用正确的ANSI JOIN语法

FROM          
   PSE.vw_EM_Data a1  
INNER JOIN           -- or possibly: LEFT OUTER JOIN or even FULL OUTER JOIN
   PSE.vw_EM_Data a2 ON a1.Sales = a2.Sales

这使得它更清楚你真正想要的是什么,并避免任何不必要的问题。

2)在你的第二个WHERE条款中,你首先不需要所有这些括号,真的 - 最重要的是,你绝对不应该转换DATE或{{ 1}}列成一个字符串然后比较它 - 所以代替这个:

DATETIME

改为使用:

WHERE     
    (Name LIKE 'John%') 
    AND (DISPOSAL = '1') 
    AND (DATE BETWEEN CONVERT(DATETIME, '2010-04-01 00:00:00', 102) AND CONVERT(DATETIME, '2011-03-30 00:00:00', 102))

我还会尝试避免使用像WHERE Name LIKE 'John%' AND DISPOSAL = '1' AND [DATE] BETWEEN '2010-04-01T00:00:00' AND '2011-03-30T00:00:00' 这样的SQL中的关键字来调用列 - 你必须在它周围使用方括号来使SQL Server清楚明白。