Mysql JOIN一个select语句

时间:2015-06-19 10:52:04

标签: mysql mariadb

我试图限制从JOIN语句中检索的行数。

考虑这些表:

CREATE TABLE `user` (
    `id` INT NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(255),
    PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `conversation` (
    `id` INT NOT NULL AUTO_INCREMENT,
    `date` DATETIME NOT NULL,
    `creator_id` INT,
    PRIMARY KEY (`id`),
    FOREIGN KEY (`creator_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB;

CREATE TABLE `message` (
    `id` INT NOT NULL AUTO_INCREMENT,
    `body` VARCHAR(4096) NOT NULL,
    `date` DATETIME NOT NULL,
    `sender_id` INT,
    `receiver_id` INT,
    `conversation_id` INT,
    PRIMARY KEY (`id`), 
    FOREIGN KEY (`sender_id`) REFERENCES `user` (`id`),
    FOREIGN KEY (`receiver_id`) REFERENCES `user` (`id`),
    FOREIGN KEY (`conversation_id`) REFERENCES `conversation` (`id`)
) ENGINE=InnoDB;

我想从涉及特定用户的20个最后一次对话中获取N个最后消息(假设ID为42的那个)

所以我的第一个想法就是这样做:

SELECT * FROM `conversation` `c`
LEFT JOIN `user` `u` ON `u`.`id` = `c`.`creator_id`
LEFT JOIN (
    SELECT * FROM `message`
    LIMIT @N
    ORDER BY `date` DESC
) `m` ON `m`.`conversation_id` = `c`.`id`
WHERE `c`.`creator_id` = 42
LIMIT 20;

由于MySQL可能会为每个会话创建一个临时表m,我只是想知道这是多么有效,或者是否有更好的方法来实现相同的结果。知道表消息和对话可能包含大量行,我只是不想限制客户端消息行的数量。

1 个答案:

答案 0 :(得分:0)

  • @N无法在LIMIT中使用。 (使用常数。)
  • ORDER BY必须在LIMIT之前。
  • 除非您真的需要,否则不要使用LEFT。优化器更喜欢从子查询开始。
  • message需要INDEX(date);没有它,它必须进行慢速扫描。

请解释您希望查询执行的操作;我还没弄清楚。