我有一张包含费用的数据表。对于任何给定的记录,我想知道记录与其他成本相关的位置。
基本上,我想知道(有多少记录的成本较低)/(记录总数)。
到目前为止,我已经提出:
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行。
答案 0 :(得分: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
这样做了吗?