MYSQL 如果用户喜欢某个状态,则将其包含在查询结果中
MYSQL if a status is liked by a user include it in query results
我在 Feed 中返回一组用户创建的状态。我已经意识到循环 mysql 导致 php post mysql 添加额外的 key/values 可笑地减慢了我们的 api 响应时间所以我试图消除此状态数组中 php 中的任何 foreach 循环。
这是我的 table 设置:
用户TABLE
UID/FIRST_NAME/LAST_NAME/ECT
更新TABLE
msg_id/message/UID_FK
喜欢TABLE
LIKED_ID/MSG_ID_FK/LIKED_BY_UID
如果发出 api 请求的用户喜欢我查询中返回的每一行的更新,我是否可以在 mysql 中包含一个 "isLiked" 布尔值?
这是我正在使用的实际查询,它的数据比我在其中描述的要多一些,但目标是相同的....找到一种方法向每一行添加一个 'isLiked' 列:
SELECT b.type,b.owner,b.update_img,b.ALBUM_ID,b.last_comment,a.uid, a.first_name, a.last_name, a.gender, a.thumb_img, b.msg_id, b.message, b.created,b.POST_PRIVACY
FROM users AS a, updates AS b, LIKED as c WHERE b.uid_fk = a.uid AND b.type<>'FRIEND_RELATIONSHIP'AND b.created<$time AND b.type<>'FAMILIAR_RELATIONSHIP' AND a.college='$college' AND b.POST_PRIVACY<>'4' AND b.POST_PRIVACY<>'5' AND b.created>=$tstamp ORDER BY b.created DESC
LIMIT 100
编辑:
这是一个查询版本,我尝试执行我的目标,但问题是这只是 returns 我喜欢的行:
SELECT b.type, b.owner, b.update_img, b.ALBUM_ID, b.last_comment, a.uid, a.first_name, a.last_name, a.gender, a.thumb_img, b.msg_id, b.message, b.created, b.POST_PRIVACY,c.LIKED
FROM users AS a, updates AS b, LIKES AS c
WHERE b.uid_fk = a.uid
AND b.POST_PRIVACY <> '4'
AND b.POST_PRIVACY <> '5'
AND c.LIKED_UID = '1'
AND b.msg_id = c.MSG_ID_FK
ORDER BY b.created DESC
LIMIT 100
如果你只得到喜欢的行但想要所有的行,试试这个:
SELECT b.type, b.owner, b.update_img, b.ALBUM_ID, b.last_comment, a.uid, a.first_name, a.last_name, a.gender, a.thumb_img, b.msg_id, b.message, b.created, b.POST_PRIVACY,c.LIKED
FROM users AS a, updates AS b, BUMPS AS c
WHERE b.uid_fk = a.uid
AND b.POST_PRIVACY <> '4'
AND b.POST_PRIVACY <> '5'
AND ((c.LIKED_UID = '1'
AND b.msg_id = c.MSG_ID_FK)
OR c.MSG_ID_FK IS NULL
)
ORDER BY b.created DESC
LIMIT 100
添加了空测试,使其等同于 LEFT JOIN
。
当该消息 ID 上有人点赞时,c.LIKED
列将为 1,否则为 null
。
-- 编辑--
上面写的不行(可能有误,我没测试),试试这种写法(我喜欢这样写):
SELECT b.type, b.owner, b.update_img, b.ALBUM_ID, b.last_comment, a.uid, a.first_name, a.last_name, a.gender, a.thumb_img, b.msg_id, b.message, b.created, b.POST_PRIVACY,c.LIKED
FROM
users AS a
INNER JOIN updates AS b ON b.uid_fk = a.uid
LEFT JOIN BUMPS AS c ON b.msg_id = c.MSG_ID_FK
WHERE b.POST_PRIVACY <> '4'
AND b.POST_PRIVACY <> '5'
ORDER BY b.created DESC
LIMIT 100
请注意,它只会 select 与用户和更新相关的行,如果不存在相关行,来自 table BUMPS 的值将 selected 为 NULL。这是我推荐的。
(删除可能导致错误和混淆的信息)
-- EDIT 2 添加了一个具有简化数据和查询的测试用例--
之前没看清问题的全貌,后来做了一个test-case。
我创建了测试 tables 和数据:
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `test_multi_sets`()
DETERMINISTIC
begin
select user() as first_col;
select user() as first_col, now() as second_col;
select user() as first_col, now() as second_col, now() as third_col;
end$$
DELIMITER ;
CREATE TABLE IF NOT EXISTS `BUMPS` (
`id` int(11) NOT NULL,
`MSG_ID_FK` int(11) NOT NULL,
`LIKED_UID` int(11) NOT NULL,
`LIKED` tinyint(4) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
INSERT INTO `BUMPS` (`id`, `MSG_ID_FK`, `LIKED_UID`, `LIKED`) VALUES
(1, 1, 1, 1),
(2, 3, 2, 0),
(3, 1, 2, 0);
CREATE TABLE IF NOT EXISTS `updates` (
`msg_id` int(11) NOT NULL,
`uid_fk` int(11) NOT NULL,
`text` varchar(20) NOT NULL,
`POST_PRIVACY` tinyint(4) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
INSERT INTO `updates` (`msg_id`, `uid_fk`, `text`, `POST_PRIVACY`) VALUES
(1, 1, 't11', 3),
(2, 1, 't12', 3),
(3, 2, 't21', 3),
(4, 2, 't22', 3);
CREATE TABLE IF NOT EXISTS `users` (
`uid` int(11) NOT NULL,
`name` varchar(20) NOT NULL,
`pass` varchar(20) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
INSERT INTO `users` (`uid`, `name`, `pass`) VALUES
(1, 'u1', 'p1'),
(2, 'u2', 'p2');
ALTER TABLE `BUMPS`
ADD PRIMARY KEY (`id`), ADD KEY `MSG_ID_FK` (`MSG_ID_FK`), ADD KEY `LIKED_UID` (`LIKED_UID`);
ALTER TABLE `updates`
ADD PRIMARY KEY (`msg_id`), ADD KEY `uid_fk` (`uid_fk`);
ALTER TABLE `users`
ADD PRIMARY KEY (`uid`);
ALTER TABLE `BUMPS`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=4;
ALTER TABLE `updates`
MODIFY `msg_id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5;
ALTER TABLE `users`
MODIFY `uid` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3;
ALTER TABLE `BUMPS`
ADD CONSTRAINT `bumps_ibfk_1` FOREIGN KEY (`LIKED_UID`) REFERENCES `users` (`uid`),
ADD CONSTRAINT `bumps_ibfk_2` FOREIGN KEY (`MSG_ID_FK`) REFERENCES `updates` (`msg_id`);
ALTER TABLE `updates`
ADD CONSTRAINT `updates_ibfk_1` FOREIGN KEY (`uid_fk`) REFERENCES `users` (`uid`);
和运行这个select:
SELECT a.uid, a.name, b.msg_id, b.text, b.POST_PRIVACY, c.LIKED
FROM users AS a
INNER JOIN updates AS b ON b.uid_fk = a.uid
LEFT JOIN BUMPS AS c ON (c.LIKED_UID = 1 AND b.msg_id = c.MSG_ID_FK)
WHERE NOT (b.POST_PRIVACY IN(4, 5)) LIMIT 100
这些结果:
| uid | name | msg_id | text | POST_PRIVACY | LIKED
| 1 | u1 | 1 | t11 | 3 | 1
| 1 | u1 | 2 | t12 | 3 | NULL
| 2 | u2 | 3 | t21 | 3 | NULL
| 2 | u2 | 4 | t22 | 3 | NULL
即使用户 2 喜欢更新,它也不会显示在用户 1 查询中。
希望本文能帮助您解决问题。我相信我不能比这更进一步了,但无论如何,如果需要请发送消息。
如果在您的生产服务器上使用它请注意,因为 EDIT 2 上的第一个脚本将创建 tables。
我在 Feed 中返回一组用户创建的状态。我已经意识到循环 mysql 导致 php post mysql 添加额外的 key/values 可笑地减慢了我们的 api 响应时间所以我试图消除此状态数组中 php 中的任何 foreach 循环。
这是我的 table 设置:
用户TABLE UID/FIRST_NAME/LAST_NAME/ECT
更新TABLE msg_id/message/UID_FK
喜欢TABLE
LIKED_ID/MSG_ID_FK/LIKED_BY_UID
如果发出 api 请求的用户喜欢我查询中返回的每一行的更新,我是否可以在 mysql 中包含一个 "isLiked" 布尔值?
这是我正在使用的实际查询,它的数据比我在其中描述的要多一些,但目标是相同的....找到一种方法向每一行添加一个 'isLiked' 列:
SELECT b.type,b.owner,b.update_img,b.ALBUM_ID,b.last_comment,a.uid, a.first_name, a.last_name, a.gender, a.thumb_img, b.msg_id, b.message, b.created,b.POST_PRIVACY
FROM users AS a, updates AS b, LIKED as c WHERE b.uid_fk = a.uid AND b.type<>'FRIEND_RELATIONSHIP'AND b.created<$time AND b.type<>'FAMILIAR_RELATIONSHIP' AND a.college='$college' AND b.POST_PRIVACY<>'4' AND b.POST_PRIVACY<>'5' AND b.created>=$tstamp ORDER BY b.created DESC
LIMIT 100
编辑:
这是一个查询版本,我尝试执行我的目标,但问题是这只是 returns 我喜欢的行:
SELECT b.type, b.owner, b.update_img, b.ALBUM_ID, b.last_comment, a.uid, a.first_name, a.last_name, a.gender, a.thumb_img, b.msg_id, b.message, b.created, b.POST_PRIVACY,c.LIKED
FROM users AS a, updates AS b, LIKES AS c
WHERE b.uid_fk = a.uid
AND b.POST_PRIVACY <> '4'
AND b.POST_PRIVACY <> '5'
AND c.LIKED_UID = '1'
AND b.msg_id = c.MSG_ID_FK
ORDER BY b.created DESC
LIMIT 100
如果你只得到喜欢的行但想要所有的行,试试这个:
SELECT b.type, b.owner, b.update_img, b.ALBUM_ID, b.last_comment, a.uid, a.first_name, a.last_name, a.gender, a.thumb_img, b.msg_id, b.message, b.created, b.POST_PRIVACY,c.LIKED
FROM users AS a, updates AS b, BUMPS AS c
WHERE b.uid_fk = a.uid
AND b.POST_PRIVACY <> '4'
AND b.POST_PRIVACY <> '5'
AND ((c.LIKED_UID = '1'
AND b.msg_id = c.MSG_ID_FK)
OR c.MSG_ID_FK IS NULL
)
ORDER BY b.created DESC
LIMIT 100
添加了空测试,使其等同于 LEFT JOIN
。
当该消息 ID 上有人点赞时,c.LIKED
列将为 1,否则为 null
。
-- 编辑--
上面写的不行(可能有误,我没测试),试试这种写法(我喜欢这样写):
SELECT b.type, b.owner, b.update_img, b.ALBUM_ID, b.last_comment, a.uid, a.first_name, a.last_name, a.gender, a.thumb_img, b.msg_id, b.message, b.created, b.POST_PRIVACY,c.LIKED
FROM
users AS a
INNER JOIN updates AS b ON b.uid_fk = a.uid
LEFT JOIN BUMPS AS c ON b.msg_id = c.MSG_ID_FK
WHERE b.POST_PRIVACY <> '4'
AND b.POST_PRIVACY <> '5'
ORDER BY b.created DESC
LIMIT 100
请注意,它只会 select 与用户和更新相关的行,如果不存在相关行,来自 table BUMPS 的值将 selected 为 NULL。这是我推荐的。
(删除可能导致错误和混淆的信息)
-- EDIT 2 添加了一个具有简化数据和查询的测试用例-- 之前没看清问题的全貌,后来做了一个test-case。
我创建了测试 tables 和数据:
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `test_multi_sets`()
DETERMINISTIC
begin
select user() as first_col;
select user() as first_col, now() as second_col;
select user() as first_col, now() as second_col, now() as third_col;
end$$
DELIMITER ;
CREATE TABLE IF NOT EXISTS `BUMPS` (
`id` int(11) NOT NULL,
`MSG_ID_FK` int(11) NOT NULL,
`LIKED_UID` int(11) NOT NULL,
`LIKED` tinyint(4) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
INSERT INTO `BUMPS` (`id`, `MSG_ID_FK`, `LIKED_UID`, `LIKED`) VALUES
(1, 1, 1, 1),
(2, 3, 2, 0),
(3, 1, 2, 0);
CREATE TABLE IF NOT EXISTS `updates` (
`msg_id` int(11) NOT NULL,
`uid_fk` int(11) NOT NULL,
`text` varchar(20) NOT NULL,
`POST_PRIVACY` tinyint(4) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
INSERT INTO `updates` (`msg_id`, `uid_fk`, `text`, `POST_PRIVACY`) VALUES
(1, 1, 't11', 3),
(2, 1, 't12', 3),
(3, 2, 't21', 3),
(4, 2, 't22', 3);
CREATE TABLE IF NOT EXISTS `users` (
`uid` int(11) NOT NULL,
`name` varchar(20) NOT NULL,
`pass` varchar(20) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
INSERT INTO `users` (`uid`, `name`, `pass`) VALUES
(1, 'u1', 'p1'),
(2, 'u2', 'p2');
ALTER TABLE `BUMPS`
ADD PRIMARY KEY (`id`), ADD KEY `MSG_ID_FK` (`MSG_ID_FK`), ADD KEY `LIKED_UID` (`LIKED_UID`);
ALTER TABLE `updates`
ADD PRIMARY KEY (`msg_id`), ADD KEY `uid_fk` (`uid_fk`);
ALTER TABLE `users`
ADD PRIMARY KEY (`uid`);
ALTER TABLE `BUMPS`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=4;
ALTER TABLE `updates`
MODIFY `msg_id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5;
ALTER TABLE `users`
MODIFY `uid` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3;
ALTER TABLE `BUMPS`
ADD CONSTRAINT `bumps_ibfk_1` FOREIGN KEY (`LIKED_UID`) REFERENCES `users` (`uid`),
ADD CONSTRAINT `bumps_ibfk_2` FOREIGN KEY (`MSG_ID_FK`) REFERENCES `updates` (`msg_id`);
ALTER TABLE `updates`
ADD CONSTRAINT `updates_ibfk_1` FOREIGN KEY (`uid_fk`) REFERENCES `users` (`uid`);
和运行这个select:
SELECT a.uid, a.name, b.msg_id, b.text, b.POST_PRIVACY, c.LIKED
FROM users AS a
INNER JOIN updates AS b ON b.uid_fk = a.uid
LEFT JOIN BUMPS AS c ON (c.LIKED_UID = 1 AND b.msg_id = c.MSG_ID_FK)
WHERE NOT (b.POST_PRIVACY IN(4, 5)) LIMIT 100
这些结果:
| uid | name | msg_id | text | POST_PRIVACY | LIKED
| 1 | u1 | 1 | t11 | 3 | 1
| 1 | u1 | 2 | t12 | 3 | NULL
| 2 | u2 | 3 | t21 | 3 | NULL
| 2 | u2 | 4 | t22 | 3 | NULL
即使用户 2 喜欢更新,它也不会显示在用户 1 查询中。
希望本文能帮助您解决问题。我相信我不能比这更进一步了,但无论如何,如果需要请发送消息。
如果在您的生产服务器上使用它请注意,因为 EDIT 2 上的第一个脚本将创建 tables。