我有一个查询,我用来构建一组数据,它应该按照每个管理员ID的评级准确包含前3个用户。 现在因为我无法使用SQL实现这一点,我将分别为每个管理员提取顶级用户,然后将它们推送到一个数组中。 更重要的是,因为调用sth-> fetchAll(),然后调用array_merge(),将导致在第二次迭代及之后出现重复的数组键,因此会导致致命错误,我也有内部迭代(循环)在第一个中,从结果集中获取每一行并将其推送到我保留格式化结果的数组中。 在我的拙见中,这导致了n * 3次迭代,其中n * 3 -1太多了。
此外,BTW问题一直困扰着我一段时间: 是否真的无法将参数或值绑定到SQL语言组件(如LIMIT等),并禁用PDO模拟的预准备语句? 代码:
private function getHotUsers($admins, $count = 3)
{
try{
$conn = DBLink::getInstance();
$rows = array();
$sql = "SELECT user_name, user_id, user_group_id FROM users
WHERE admin_id= :uid AND status=1 ORDER BY is_hot_user DESC,last_updated DESC LIMIT {$count}";
$sth = $conn->prepare($sql);
foreach ($admins as $admin)
{
$sth->bindParam(':uid', $admin, PDO::PARAM_INT);
$sth->execute();
while($row = $sth->fetch(PDO::FETCH_ASSOC)){
$rows[] = $row;
}
}
return $rows;
}
}
| Field | Type | Null | Key | Default | Extra |
+----------------------+------------------+------+-----+---------+----------------+
| user_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| admin_id | int(20) | NO | | NULL | |
| user_title | varchar(450) | NO | | NULL | |
| user_desc | varchar(5000) | NO | | NULL | |
| user_data | longtext | NO | | NULL | |
| user_requirements | varchar(5000) | YES | | NULL | |
| user_experience | varchar(100) | NO | | NULL | |
| location_id | int(11) unsigned | NO | | NULL | |
| comp_id | int(11) | NO | | NULL | |
| role_id | int(10) unsigned | NO | | NULL | |
| user_pass_time | varchar(100) | YES | | NULL | |
| last_updated | datetime | NO | | NULL | |
| is_hot_user | tinyint(1) | NO | | 0 | |
| user_internal_id | int(10) | YES | | NULL | |
+----------------------+------------------+------+-----+---------+----------------+
INSERT INTO USERS(admin_id,last_updated,是hot_user) VALUES (1,NOW() - INTERVAL 10 DAY,1),(1,NOW() - INTERVAL 1 DAY,0), (1,NOW() - INTERVAL 100 DAY,1),(1,NOW() - INTERVAL 8 DAY,0),
(2,NOW() - INTERVAL 1 DAY,1),(2,NOW() - INTERVAL 100 DAY,1), (2,NOW() - INTERVAL 5 DAY,1),(2,NOW(),0),
(3,NOW(),0),(3,NOW() - INTERVAL 1 DAY,0),(3,NOW() - 100 DAY,1), (3,NOW() - INTERVAL 4 DAY,0),(3,NOW() - INTERVAL 5 DAY,0)
根据@VolkerK的要求编辑,粗体是应该由查询选择的行,前3个热门用户,在last_updated列中也具有最新值,或者只有最新用户(如果少于热门用户tan 3为此特定管理员
答案 0 :(得分:0)
不。看来你已经在使用正确的方式了 虽然你也可以绑定$ count。 此外,虽然调用$ sth-> fetchAll(),然后调用array_merge(),不会导致重复键(这是不可能的,请注意),我不会合并所有用户无论如何,进入单个数组,而是通过他们的管理员对它们进行分组
private function getHotUsers($admins, $count = 3)
{
$conn = DBLink::getInstance();
$rows = array();
$sql = "SELECT user_name, user_id, user_group_id FROM topUsers
WHERE admin_id= :uid AND status=1
ORDER BY is_hot_user DESC,last_updated DESC
LIMIT :coint";
$sth = $conn->prepare($sql);
foreach ($admins as $admin)
{
$sth->bindParam(':uid', $admin, PDO::PARAM_INT);
$sth->bindParam(':count', $count, PDO::PARAM_INT);
$sth->execute();
$rows[$admin] = $sth->fetchAll();
}
return $rows;
}
让你的困惑直截了当:
答案 1 :(得分:-2)
我不会在循环中执行这样的查询。第一种解决方案是使用… IN (…)
搜索ID列表(如Rob所建议的那样)。
或者您只需在循环中设置查询和参数,然后在循环后执行语句。
$start = 0;
$limit = 100;
$placeholderArray = $valuesArray = array( );
$i = 0;
foreach( $admins as $adminId )
{
$placeholderArray[] = sprintf( ' `admin_id` = :admin%d ', $i );
$valuesArray[sprintf( ':admin%d', $i )] = (int) $adminId;
$i++;
}
$where = ' (' . implode( ' OR ', $placeholderArray ) . ') ';
$sql = sprintf( 'SELECT user_name, user_id, user_group_id
FROM topUsers
WHERE status=1
%s
ORDER BY is_hot_user DESC,last_updated DESC
LIMIT %d,%d;', $where, $start, $limit );
$stmt = $conn->prepare( $sql );
if( $stmt->execute( $valuesArray ) === true )
{
/* … */
}
通过将原始输入限制为数组$admins
中的三个条目,可以实现对三个条目的限制。