2017-04-09 69 views
1

我希望能够深入了解mySQL如何处理这个问题。 所以我想获得某一列中元素的中位数。看到问题here。我一直在试图获取变量@ct中的总行数,并得出一个表格,其中所有行都按照所讨论的列的值进行编号和排序。 然后我简单地查询其行满足条件的列的平均值,并且标准取决于@ct是奇数还是偶数。以下是该工作代码。mySQL中CASE函数的怪异工作

SET @ct := (select count(*) from STATION); %This stores the number of rows 
SET @rowNum :=0; %This will be used to save row number for each row. 


SELECT AVG(q.LAT_N) 

FROM (SELECT LAT_N,(@rowNum:[email protected]+1) n FROM STATION ORDER BY LAT_N) AS q 

WHERE q.n = (CASE @ct%2 WHEN 1 THEN (@ct+1)/2 ELSE @ct/2 OR (@ct+1)/2 END) 

奇怪的是,当在最后一行,而不是使用或排序对两个值我这样做,

WHERE q.n = (CASE @ct%2 WHEN 1 THEN (@ct+1)/2 ELSE (@ct/2,(@ct+1)/2) END) 

OR

WHERE q.n IN (CASE @ct%2 WHEN 1 THEN (@ct+1)/2 ELSE (@ct/2,(@ct+1)/2) END) 

我不断收到语法错误Operand should contain 1 column(s) 任何想法是怎么回事?我是否缺少一些基本的语法规则? 我也尝试过与IF函数相同的功能。

+1

我不认为_(@ ct/2,(@ ct + 1)/ 2)_是一个有效的表达式,因为逗号。它将评估为两列,并且您正在针对一列进行测试 –

+0

但我们不在'IN'子句中这样做吗? –

+0

'IN'只针对多行而不是多列进行测试。您可以将其视为行向量与列向量。 – THN

回答

1

您的方法存在多个问题。

由于@ct/2 OR (@ct+1)/2将始终返回1TRUE),所以您的第一个查询将不能用于偶数。所以你会永远得到最小的价值。

您的第二个WHERE条件不起作用,因为CASE表达式不能返回多个列。你可以做的是使用BETWEEN条件:

WHERE q.n BETWEEN (CASE @ct%2 WHEN 1 THEN (@ct+1)/2 ELSE @ct/2 END) 
       AND (CASE @ct%2 WHEN 1 THEN (@ct+1)/2 ELSE (@ct+1)/2 END) 

或者

WHERE 
    CASE WHEN @ct%2 
     THEN q.n = (@ct+1)/2 
     ELSE q.n BETWEEN @ct/2 AND (@ct+1)/2 
    END 

然而(@ct+1)/2是错误的,甚至数和应@ct/2+1

但是你甚至不需要CASE表达式。你也可以使用

WHERE q.n BETWEEN @ct/2 
       AND @ct/2+1 
0

这不是你的问题的答案。但我认为这是解决您的问题。

SET @ct := (select count(*) from STATION); 
SET @rowNum :=0; 
SET @start := floor((@ct+1)/2); 
SET @end := ceil((@ct+1)/2); 

SELECT AVG(q.LAT_N) 

FROM (SELECT LAT_N,(@rowNum:[email protected]+1) n FROM STATION ORDER BY LAT_N) AS q 

WHERE q.n in(@start,@end); 

请尝试一下。

+0

谢谢,但我已发布的代码实际上工作。我只是想知道为什么它不能像我发布的那样使用其他方式。 –