我在Feed中返回一组用户创建的状态。我已经意识到循环通过mysql导致php post mysql添加额外的键/值可笑地减慢了我们的api响应时间所以我试图消除在这个状态数组的PHP中的任何foreach循环。
这是我的表格设置:
USERS TABLE UID / FIRST_NAME / LAST_NAME / ECT
更新表 msg_id / message / UID_FK
LIKED TABLE
LIKED_ID / MSG_ID_FK / LIKED_BY_UID
有没有办法在mysql中我可以包含一个“isLiked”bool如果发出api请求的用户喜欢我查询中返回的每一行的更新?
这是我正在使用的实际查询,它有比我描述的更多的数据,但目标是相同的....找到一种方法为每一行添加'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
编辑:
这是查询的一个版本,我尝试做的目标是什么,但问题是这只会返回我喜欢的行:
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
答案 0 :(得分:2)
如果您只获得喜欢但想要所有行的行,请尝试以下操作:
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
列将为<{p}}。
- 编辑 -
由于上述方法不起作用(可能是错误的,我没有测试过),试试这种形式(我喜欢这种方式):
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
请注意,它只会选择与用户和更新相关的行,如果不存在相关行,则表BUMPS中的值将被选为NULL。这就是我的建议。
(删除可能导致错误并导致混淆的信息)
- EDIT 2添加了一个包含简化数据和查询的测试用例 - 之前我没有看到整个问题,然后我做了一个测试用例。
我创建了测试表和数据:
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 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喜欢更新,也不会在user1查询中显示。
我希望这可以帮助您解决问题。我相信我不能再进一步了,但无论如何,如果需要,请发送信息。
如果在生产服务器上使用它,请注意,因为EDIT 2上的第一个脚本将创建表。