MYSQL如果用户喜欢状态,则将其包含在查询结果中

时间:2015-08-02 05:49:22

标签: mysql sql performance select conditional

我在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 

1 个答案:

答案 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上的第一个脚本将创建表。