1

我有一个包含成本的数据表。对于任何给定的记录,我想知道该记录相对于其他成本的位置。

基本上,我想知道(有多少记录成本较低)/(记录总数)。

到目前为止,我想出了:

SELECT (SUM(IF(r.cost > c.cost, 1, 0)) + 1) / COUNT(1) as percent_rank 
FROM record r, 
   (SELECT cost FROM record WHERE cost IS NOT NULL) as c 
WHERE r.id = 10;

在此查询上运行 EXPLAIN 会产生:

+----+-------------+------------+-------+---------------+---------+---------+-------+-------+-------------+
| id | select_type | table      | type  | possible_keys | key     | key_len | ref   | rows  | Extra       |
+----+-------------+------------+-------+---------------+---------+---------+-------+-------+-------------+
|  1 | PRIMARY     | r          | const | PRIMARY       | PRIMARY | 4       | const |     1 |             |
|  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL  | 21469 |             |
|  2 | DERIVED     | record     | ALL   | NULL          | NULL    | NULL    | NULL  | 21469 | Using where |
+----+-------------+------------+-------+---------------+---------+---------+-------+-------+-------------+

有没有更好的方法来运行这个查询?21469 是表中的所有记录。我有点担心交叉连接,但是这个查询总是用 id = something 运行,所以它只有 1 * 总 num 行。

4

1 回答 1

0

我建议在子查询中获取 r.cost 的值,或者如果有可能将其放入查询中引用的变量而不是连接中,因为这样可以简化您需要的逻辑:

DECLARE @thisCost Cost_Datatype;
SELECT @thisCost = cost FROM record WHERE id = 10;

意味着查询现在看起来像:

SELECT (SUM(IF(@thisCost > cost, 1, 0)) + 1) / COUNT(1) as percent_rank 
FROM record 
WHERE cost IS NOT NULL 

移除了连接的复杂性后,条件也可以移除,并且引擎允许将查询作为集合操作来回答,方法是将总行数放在它自己的(子)查询中:

SELECT (Count(*) / (SELECT Count(*) FROM record)) as [% with lower cost]
FROM record
WHERE cost IS NOT NULL AND @thisCost > cost

那能行吗?

于 2013-09-26T00:15:48.227 回答