[英]Get 3 highest values from table
我想计算具有最多归因行的前 3 个用户。
SQL表:
ID | IdUser | Type |
-----------------------
0 | 1 | like |
1 | 1 | like |
2 | 4 | dislike |
3 | 5 | dislike |
4 | 1 | like |
5 | 4 | like |
6 | 5 | like |
8 | 4 | like |
9 | 4 | like |
10 | 3 | like |
11 | 5 | like |
12 | 9 | like |
结果应该是:
idUser[1] with 3 times "like" and 0 "dislike" (3-0 = 3 points)
idUser[4] with 3 times "like" and 1 "dislike" (3-1 = 2 points)
idUser[5] with 2 times "like" and 1 "dislikes (2-1 = 1 point )
所以我想要做的是获得 idUser 1(3 分),然后是 idUser4(2 分),最后是 idUser 5(1 分)和他们的分数。
我尝试了不同的方法,但都没有奏效。
在这里,我尝试使用所有数据创建一个二维数组,然后获取最高值,但我无法执行第二部分。
表“users”记录了网站的所有用户表“points”记录了喜欢和不喜欢
$sqlUsers = "SELECT * FROM users";
$resultUsers = $conn->query($sqlUsers);
$recordsArray = array(); //create array
while($rowUsers = $resultUsers->fetch_assoc()) {
$idUser = $rowUsers['id'];
//COUNT LIKES OF THE USER
$sqlLikes = "SELECT COUNT(id) AS numberLikes FROM points WHERE idCibledUser='$idUser' AND type='like'";
$resultLikes = $conn->query($sqlLikes);
$rowLikes = $resultLikes->fetch_assoc();
//COUNT DISLIKES OF THE USER
$sqlDislikes = "SELECT COUNT(id) AS numberDislikes FROM points WHERE idCibledUser='$idUser' AND type='dislike'";
$resultDislikes = $conn->query($sqlDislikes);
$rowDislikes = $resultDislikes->fetch_assoc();
//GET POINTS BY SUBTRACTING DISLIKES FROM LIKES
$points = $rowLikes['numberLikes'] - $rowDislikes['numberDislikes'];
$recordsArray[] = array($idUser => $points);
}
如果您最终只需要总分而没有喜欢和不喜欢的细分(从您的问题中并不完全清楚):
SELECT IdUser, SUM(IF(Type='like',1,-1)) AS points
FROM users
GROUP BY IdUser
ORDER BY points DESC
LIMIT 3
如果你想要完整的细分:
SELECT IdUser,
SUM(IF(Type='like',1,-1)) AS points,
SUM(IF(Type='like',1,0)) as likes,
SUM(IF(Type='dislike',1,0)) as dislikes
FROM users
GROUP BY IdUser
ORDER BY points DESC
LIMIT 3
解释
假设我想计算Type
列值为'like'
的总行数。 我可以执行以下操作:
SELECT COUNT(*) AS cnt FROM users WHERE Type = 'like'
但另一种可能不太直接的方法是:
SELECT SUM(IF(Type = 'like', 1, 0)) AS cnt FROM users
在上面的 SQL 中,正在检查每行中的Type
列,如果等于'like'
,则将 1 的值分配给该列,否则为 0。然后使用SUM
函数将所有这些 1 和 0 相加。 通过将所有 1 相加,您实际上是在计算Type
列中具有'like'
的行数。 第二种方法允许您一次处理喜欢和不喜欢的数量:
SELECT SUM(IF(Type = 'like', 1, 0)) AS likes,
SUM(IF(Type = 'dislike', 1, 0)) AS dislikes
FROM users
但是,如果您想逐个用户地获得上述计数怎么办? 这就是GROUP BY
子句的目的:
SELECT IdUser,
SUM(IF(Type = 'like', 1, 0)) AS likes,
SUM(IF(Type = 'dislike', 1, 0)) AS dislikes
FROM users
GROUP BY IdUser
如果我们将值 1 分配给包含'like'
的列,如果包含'dislike'
(或不是'like'
则将值分配给 -1,则可以计算“分数”或喜欢和不喜欢之间的差异),然后将这些值相加:
SELECT IdUser,
SUM(IF(Type = 'like', 1, -1)) AS points,
SUM(IF(Type = 'like', 1, 0)) as likes,
SUM(IF(Type = 'dislike', 1, 0)) as dislikes
FROM users
GROUP BY IdUser
最后,如果您想要三个最高分,请按降序对返回的行进行排序( ORDER BY points DESC
)并仅保留返回的前 3 行( LIMIT 3
):
SELECT IdUser,
SUM(IF(Type = 'like', 1, -1)) AS points,
SUM(IF(Type = 'like', 1, 0)) as likes,
SUM(IF(Type = 'dislike', 1, 0)) as dislikes
FROM users
GROUP BY IdUser
ORDER BY points DESC
LIMIT 3
如果您需要经常获得喜欢/不喜欢,请参阅下面的解决方案, points
表经常更新并且数据相关性很重要,即您不想缓存结果。
创建另一个表,如user_points_summary
,它将有 2 列,例如IdUser
和Points
。 IdUser
要在此表中是唯一的,必须在将新行添加到points
表时触发Points
重新计算(每个用户)。
如果您需要喜欢/不喜欢细分,那么此表将有 3 列 - IdUser
(不再是唯一的)、 likes_count
、 dislikes_count
。 然后相同 - 在points
表中插入/更新/删除行时触发此表更新。
如果您选择第二个选项(按喜欢/不喜欢细分) - 这是创建表语句的示例:
CREATE TABLE `user_points_summary` (
`IdUser` int(11) NOT NULL,
`likes_count` int(11) NOT NULL DEFAULT '0',
`dislikes_count` int(11) NOT NULL DEFAULT '0',
KEY `idx_user_points_summary_IdUser` (`IdUser`)
) ENGINE=InnoDB;
然后您可以将以下触发器添加到您的users
表中,这将在添加新用户时添加零个喜欢/不喜欢:
CREATE TRIGGER `users_AFTER_INSERT` AFTER INSERT ON `users` FOR EACH ROW
BEGIN
INSERT INTO `user_points_summary` VALUE (NEW.`IdUser`, 0, 0);
END
然后将以下触发器添加到points
表中以更新user_points_summary
喜欢/不喜欢计数:
DELIMITER $$
CREATE TRIGGER `points_AFTER_INSERT` AFTER INSERT ON `points` FOR EACH ROW
BEGIN
IF NEW.`Type` = 'like' THEN
UPDATE `user_points_summary` SET `likes_count` = `likes_count` + 1 WHERE `IdUser` = NEW.`IdUser`;
ELSEIF NEW.`Type` = 'dislike' THEN
UPDATE `user_points_summary` SET `dislikes_count` = `dislikes_count` + 1 WHERE `IdUser` = NEW.`IdUser`;
END IF;
END $$
CREATE TRIGGER `points_AFTER_UPDATE` AFTER UPDATE ON `points` FOR EACH ROW
BEGIN
IF NEW.`Type` = 'dislike' AND OLD.`Type` = 'like' THEN
UPDATE `user_points_summary`
SET
`likes_count` = `likes_count` - 1,
`dislikes_count` = `dislikes_count` + 1
WHERE `IdUser` = `OLD`.`IdUser`;
ELSEIF NEW.`Type` = 'like' AND OLD.`Type` = 'dislike' THEN
UPDATE `user_points_summary`
SET
`dislikes_count` = `dislikes_count` - 1,
`likes_count` = `likes_count` + 1
WHERE `IdUser` = OLD.`IdUser`;
END IF;
END $$
CREATE TRIGGER `points_AFTER_DELETE` AFTER DELETE ON `points` FOR EACH ROW
BEGIN
IF OLD.`Type` = 'like' THEN
UPDATE `user_points_summary`
SET `likes_count` = `likes_count` - 1
WHERE `IdUser` = `OLD`.`IdUser`;
ELSEIF OLD.`Type` = 'dislike' THEN
UPDATE `user_points_summary`
SET `dislikes_count` = `dislikes_count` - 1
WHERE `IdUser` = OLD.`IdUser`;
END IF;
END $$
DELIMITER ;
然后您可以使用以下查询来获取用户点数的喜欢和不喜欢计数:
SELECT *, `likes_count` - `dislikes_count` AS `points`
FROM `user_points_summary`
ORDER BY `points` DESC
LIMIT 3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.