使用百分比选择(LIMIT X,1)获取行号的最快方法?
Posted
技术标签:
【中文标题】使用百分比选择(LIMIT X,1)获取行号的最快方法?【英文标题】:Fastest way to get row number with percentage selects (LIMIT X, 1)? 【发布时间】:2013-05-20 15:35:31 【问题描述】:在我的 mysql 数据库中,我有一个包含超过 1000 万行的表 (PERSONS),两个重要的列是:
身份证 要点我想知道 ID = randomid 的人的等级
我想将他的“等级”归还给这个人,这取决于他的积分。 但他的排名不会是确切的行号,而更像是一个百分比层。比如:“你在前 5%”或“你在 10% - 15% 的层”。
当然,我可以通过将行数除以总行数来查询表并将行数转换为层%。但我的问题是,用 LIMIT X, 1 抓取几行是否会更快(有 10M+ 行),其中 X 将是表格百分比 100、95、90、85 .. 上的一行。下一步:检查该行的点数是否低于当前人的点数,如果是,则抓取下一层%行,如果不是,则返回上一层行。
persons 表中有 9 列,其中包含 2 个 bigint、4 个 varchars 150、1 个日期和 2 个布尔值。
当然,我更希望得到确切的行排名,但根据我的测试,这很慢,至少需要几秒钟,而我的 wat 可以在几百秒内完成。
另外,我建议的方式在有多个相同点的层时并不精确,但不需要那么精确,所以我们可以忽略这个事实。
额外信息,我用 php 编程,所以如果在 PHP + MySQL 中有特定的解决方案,那也很好。
最后,值得一提的是,该表以每小时 20k 行的速度增长(几乎每天 500k)。
感谢所有帮助。
【问题讨论】:
这似乎是关于mysql和百分位数的问题。我说的对吗? 是的,我的意思是百分位数。 :) 【参考方案1】:你可以试试这个。我首先计算具有 more 个点的行数,然后将其加一,以防有许多行具有相同的点数。因此,如果有 10 行具有相同的点数,则它们的排名都与该组中的第一行相同。
SELECT SUM(CASE WHEN points > (SELECT POINTS FROM YOUR_TABLE WHERE ID = randomid) THEN 1 ELSE 0 END) + 1 as Rank,
(SUM(CASE WHEN points > (SELECT POINTS FROM YOUR_TABLE WHERE ID = randomid) THEN 1 ELSE 0 END) + 1) / COUNT(*) as Pct
FROM YOUR_TABLE
如果这很慢,我会运行两个查询。首先获取该 ID 的分数,然后将其插入第二个查询以确定排名/pct。
SELECT POINTS
FROM YOUR_TABLE
WHERE ID = randomid
然后计算排名和 pct,从上面插入点。
SELECT SUM(CASE WHEN points > POINTS THEN 1 ELSE 0 END) + 1 as Rank,
(SUM(CASE WHEN points > POINTS THEN 1 ELSE 0 END) + 1) / COUNT(*) as Pct
FROM YOUR_TABLE
【讨论】:
Pct 就是我所说的百分比计算。你可以叫它任何东西。 在有 600k 行的测试表上,它真的很快,0.3 秒。这真是太好了。此解决方案是否比使用行数选择更快?我对 SQL 很陌生,所以我不完全理解您的查询:) 我也是 *** 的新手,所以你知道。 有许多不同的方法可以做到这一点。这可能不是最快的,但它相对整洁。最快的方法可能是进行 3 次调用并将结果存储在 PHP 变量中,然后进行数学运算。首先,您将获得相关 ID 的点数SELECT POINTS FROM YOUR_TABLE WHERE ID = randomid
,然后获得排名SELECT COUNT(*) + 1 FORM YOUR_TABLE WHERE POINTS > <points from above>
,然后获得总记录SELECT COUNT(*) FROM YOUR_TABLE
。以上是关于使用百分比选择(LIMIT X,1)获取行号的最快方法?的主要内容,如果未能解决你的问题,请参考以下文章
在 concurrent.futures 中获取异常的原始行号