Php 从表中获取3个最高值
我想数一数拥有最多属性行的前3个用户 SQL表:Php 从表中获取3个最高值,php,mysql,Php,Mysql,我想数一数拥有最多属性行的前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
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分),然后是idUser 4(2分),最后是idUser 5(1分)
我试过不同的方法,但都不管用
在这里,我试图创建一个包含所有数据的二维数组,然后获得最高值,但我无法完成第二部分
表“用户”包含网站的所有用户
表“点”记录了喜欢和不喜欢的内容
$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);
}
如果您需要经常获取喜欢/不喜欢的内容,请参阅下面的解决方案,
点
表经常更新,数据相关性很重要,即您不想缓存结果
创建另一个表,如user\u points\u summary
,该表将有两列,例如IdUser
和points
IdUser
要在此表中唯一,必须在向点
表中添加新行时触发点
重新计算(每个用户)
如果需要喜欢/不喜欢细分,则此表将有3列-IdUser
(不再唯一)、likes\u count
、dislikes\u count
。然后相同-在插入/更新/删除点
表中的行时触发此表更新
如果使用第二个选项(使用喜欢/不喜欢细分)-下面是CREATETABLE语句的示例:
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
然后将以下触发器添加到点
表中,以更新用户点_摘要
喜欢/不喜欢计数:
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
然后,您可以使用以下查询获取具有“喜欢”和“不喜欢”计数的用户点:
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
如果您最终只需要总分,而不需要对喜欢和不喜欢进行细分(您的问题不完全清楚): 如果您想要完整的细分:
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
但另一种可能不那么直接的方式是:
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相加,实际上是在计算类型
列中具有'like'
的行数。第二种方法允许您一次处理喜欢和不喜欢的数量:
SELECT SUM(IF(Type = 'like', 1, 0)) AS likes,
SUM(IF(Type = 'dislike', 1, 0)) AS dislikes
FROM users
但是,如果您希望逐个用户获得上述计数,该怎么办?这就是分组依据
条款的目的:
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'
的列,并将值-1分配给包含'loke'
(或不是'like'
)的列,然后将这些值相加,则可以计算“分数”或喜欢与不喜欢之间的差异:
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
):
你能展示一下你的尝试和结果吗?@PatrickQ我刚刚编辑了我的帖子。有任何答案解决了这个问题吗?到目前为止,您已经收到了两条消息。警告:您对参数化预处理语句非常开放,应该使用参数化预处理语句,而不是手动生成查询。它们由或提供。永远不要相信任何形式的输入!即使您的查询仅由受信任的用户执行。我不认为你的问题是关于mysqli的。我要把它改成MySQL tag,第二个代码正是我所需要的!谢谢你的回答。但是我想知道它是怎么工作的,你能给我一些简单的解释吗?我明白了。再次感谢:)是的,@Booboo回答了我的问题,但你的代码仍然很有趣。我只是想知道mysql必须执行的任务是否变得太重要了,尤其是在有几百个数据库的情况下entries@Azelkan是的,你是对的,有几百个条目,我的解决方案就太过分了