我试图弄清楚如何使用PHP确定特定数字范围内的总行数。
我有一个简单的MySQL表,只有一列。该列包含数千行,每行包含0到100之间的数字。
我想出了如何使用array_count_values查找特定数字的行数,但我无法弄清楚如何找到某个范围的行数。
例如,60到80之间有多少个数字?
这是我放在一起查找单个值的代码。我应该添加什么代码来查找范围值?
$query = "SELECT numbers FROM table";
$result = mysqli_query($conn, $query) or die("Error in $query");
$types = array();
while(($row = mysqli_fetch_assoc($result))) {
$types[] = $row['numbers'];
}
$counts = array_count_values($types);
echo $counts['12'];
答案 0 :(得分:2)
如果您需要在多个范围内进行计数,可以使用UNION
,这样您就不必发送5个查询。
$query = "SELECT COUNT(numbers) FROM `table` WHERE numbers between 00 and 20
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 20 and 40
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 40 and 60
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 60 and 80
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 80 and 100";
答案 1 :(得分:1)
你可以通过以下几种方式做到这一点。
SELECT SUM(IF(x BETWEEN 20 AND 30, 1, 0)) AS b_20_30,
SUM(...) AS b_31_40,
...
FROM tableName...
只会在表扫描时返回包含所有结果的一行。
如果您可以提出规则将时间间隔映射到单个数字,例如:
0...9 => interval i = 0
10...19 => interval i = 1 => the rule is "i = FLOOR(X/10)"
20...29 => interval i = 2
...而且您不需要扫描太多行,您可能会执行不太可维护这样的事情:
SELECT SUM(FLOOR(POW(100, FLOOR(x / 10)))) AS result FROM tableName;
这里,25(20到29之间)的值将变为2,并且总和将增加100 2 。只要你在每组中没有超过100行,最终结果将是单义的权力总和,如果你有 - 比如说 - 在0到9之间的17行,在10到19之间的31行,以及在20之间的74行和29,你会得到一个“神奇的客厅技巧”答案
743117
从那里你可以按顺序恢复行数为74,31,17。
使用1000代替100将产生74031017(并且每组中最多可以处理999个数字)。
请注意,在SELECT中使用函数几乎可以保证您需要完整,慢速的表扫描。
但我们可以通过明智地使用索引的WHERE来摆脱表扫描并简化生成 - 这在性能方面与UNION相同,但结果更简单,因为它只有一行:
SELECT (SELECT COUNT(*) FROM tableName WHERE x BETWEEN ...) AS b_20_30,
(...)
; -- no table name on the outer query
这将需要几个子查询(每个间隔一个),但这些子查询将全部使用x
上的索引(如果可用),这可以使整个查询非常快。你只需要
CREATE INDEX x_ndx ON tableName(x);
假设我们将间隔指定为方便的数组,我们可以使用PHP首先生成查询。无需手动输入所有这些SELECT。
$intervals = [ [ 20, 30 ], [ 17, 25 ], ... ];
function queryFromIntervals(array $intervals) {
$index = 0;
return 'SELECT ' .
implode(',', array_map(
function($interval) use ($tableName, &$index) {
return "(SELECT COUNT(1) FROM {$tableName} WHERE x BETWEEN {$interval[0]} AND {$interval[1]}) AS b_" . ($index++);
},
$intervals
))
// . ", (SELECT COUNT(*) FROM {$tableName}) AS total"
. ';';
}
这将再次生成一行,其中包含名为b_0
,b_1
的字段,依此类推。它们将包含x的值在$intervals
中相应区间的边界之间的行数(区间可能重叠)。
因此,通过执行查询并检索名为$result
的元组,您可能会得到
[ 'b_0' => 133, 'b_1' => 29 ]
意味着有133行,x在20到30之间,29有x在17到25之间。您可以在查询中添加最后一个总字段(在上面的代码中注释):
, ... ( SELECT COUNT(*) FROM tableName ) AS total;
也可以获得总行数。
答案 2 :(得分:0)
如果我理解得很好,你会尝试在你的请求中添加一个条件sql。 看看https://www.w3schools.com/sql/sql_where.asp
$query = "SELECT numbers FROM table WHERE numbers >= 60 AND numbers <= 80";