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。