【问题标题】:getting data from multiple tables in single query -mysql在单个查询中从多个表中获取数据 -mysql
【发布时间】:2013-10-30 11:15:02
【问题描述】:

我使用这些查询来选择具有相似阅读选择的用户的 user_ids。

SELECT r2.user_id
FROM `read` r1
JOIN `read` r2
ON r1.user_id <> r2.user_id AND r1.book_id = r2.book_id
WHERE r1.user_id = 1
GROUP BY r2.user_id
HAVING count(*) >= 5

但我不想简单地显示 user_id。还有其他表中有关此 user_id 的数据!

上面的查询只使用这个表:

CREATE TABLE `read` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(11) unsigned NOT NULL,
  `book_id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `No duplicates` (`user_id`,`book_id`),
  KEY `book_id` (`book_id`),
  CONSTRAINT `connections_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `connections_ibfk_2` FOREIGN KEY (`book_id`) REFERENCES `books` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

但我也有:

CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `email` char(255) NOT NULL DEFAULT '',
  `password` char(12) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE `books` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `book` char(55) NOT NULL DEFAULT '',
  `user_id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `book` (`book`),
  KEY `user_id` (`user_id`),
  CONSTRAINT `books_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

因此,对于我的查询生成的列表中的每个 user_id,我还希望拥有来自 usersemail。以及为该用户阅读的所有 book_ids,但这些 book_ids 是 ids,我希望它根据 book_ids 显示书籍中的书籍。

哇,有人能看懂我写的吗?

:L)

【问题讨论】:

  • 只需加入您需要的任何表并从中选择所需的列
  • @wxyz just join 不够模糊,我对 sql 不是很熟悉 :) 我正在阅读...
  • @wxyz 我应该在哪里添加另一个连接?
  • @wxyz - 可怕的建议 --> 你有没有看过他的询问?它基于 HAVING 逻辑子句。你不能只是JOIN
  • @wxyz - 我们中的一个人不明白 OP 想要什么。他的第一个查询列出了至少有 5 本书共有的用户(user=1)。请求的解决方案需要有相同的用户和他们的电子邮件(此时没有额外的行)然后他们有共同的书籍,这将为每个用户增加至少 4 行 - 有效地将记录集的大小增加至少5x(至少根据我的理解)

标签: php mysql sql


【解决方案1】:

试试这个。希望没有语法错误。如果不行,请到 SQLFiddle.com 加载一些测试数据

SELECT users.id, users.email, book.books
FROM (
  SELECT r2.user_id
  FROM `read` r1
  JOIN `read` r2
    ON r1.user_id <> r2.user_id 
      AND r1.book_id = r2.book_id
  WHERE r1.user_id = 1
  GROUP BY r2.user_id
  HAVING count(*) >= 5) as t1
 JOIN users
   ON t1.user_id = users.id
 JOIN read
   ON read.user_id = t1.user_id
 JOIN books
   ON books.id = read.book_id
 WHERE EXISTS(SELECT * 
              FROM read 
              WHERE read.user_id = 1 
                AND read.book_id = book.id)

用一个列表来总结——按书籍共同降序排序:

SELECT users.id, users.email, t1.qty, GROUP_CONCAT(book.books)
FROM (
  SELECT r2.user_id, COUNT(*) AS qty
  FROM `read` r1
  JOIN `read` r2
    ON r1.user_id <> r2.user_id 
      AND r1.book_id = r2.book_id
  WHERE r1.user_id = 1
  GROUP BY r2.user_id
  HAVING count(*) >= 5) as t1
 JOIN users
   ON t1.user_id = users.id
 JOIN read
   ON read.user_id = t1.user_id
 JOIN books
   ON books.id = read.book_id
 WHERE EXISTS(SELECT * 
              FROM read 
              WHERE read.user_id = 1 
                AND read.book_id = book.id)
 GROUP BY users.id, users.email, t1.qty
 ORDER BY t1.qty DESC, users.email ASC

【讨论】:

  • 像魅力一样工作!我正在尝试学习这些连接,但我需要更好的文档,我什么都不懂我将如何结合这些结果?我只需要他们有共同点的一串词。我应该在 php 中执行此操作吗?处理数组并改变它?
  • 附注这个查询被认为很重吗?它的扩展性如何?
  • 就heavy而言,查询并不完美,因为它会回到read表以获取更多信息。但我现在不会担心。最坏的情况 - 这会成为一个瓶颈,然后为您的第一个查询的结果构建一个临时/缓存表,并每隔... 1 小时、1 天等更新表
  • 再次,效果很好。你从哪里学到这么多关于 sql 的知识?既然你是大师,我会问你最后一个问题:D 当然,如果你同意的话。是否可以根据他们共有的书籍数量来排序?所以列表应该从匹配最多的用户开始......
  • 在学习方面,我的经验来自经验(实际上来自失败——比我想承认的失败更多:))。 StackOverflow 是解决问题的绝佳资源。我发现阅读 SO 帖子以了解其他人如何使用比我使用的更好的技术解决问题更有价值。
【解决方案2】:

试试这个

    SELECT r2.user_id,u1.email,b1.books
    FROM `read` r1
    JOIN `read` r2
    ON r1.user_id <> r2.user_id AND r1.book_id = r2.book_id
    JOIN `users` u1
    ON r2.user_id =u1.id
    JOIN `books` b1
    ON r1.book_id=b1.id
    WHERE r1.user_id = 1
    GROUP BY r2.user_id
    HAVING count(*) >= 5

【讨论】:

  • ON r2.user_id =u1.id 而不是 ON r1.user_id =u1.id 否则它只会返回 r1_user_id = 1 的额外字段电子邮件。
  • @SandroDzneladze thanx mate..made changes
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-18
  • 2016-04-28
  • 1970-01-01
  • 1970-01-01
  • 2020-11-29
  • 1970-01-01
相关资源
最近更新 更多