我有用户表:
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;
阅读表格:
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;
我想用user_id = 1来创建其他user_id的列表 - 匹配点是他们读过的常用书。因此,如果user_id = 1且user_id = 2共有5本书,那么user_id应该在该列表中。我不太擅长sql,所以任何关于如何实现这一点的建议,甚至是很少的优化提示都将非常感激。
答案 0 :(得分:1)
可能的解决方案 - 为用户提供阅读5本或更多通用书籍
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
如果用户必须拥有5本共同书籍(不得少于,不能更多),则HAVING
的条款必须更改为:
HAVING count(*) = 5
演示: - &gt; http://www.sqlfiddle.com/#!2/7a9b7/1
对查询的简单更改会为读取&gt; = 5本常用书籍的用户提供一对:
SELECT r1.user_id user1, r2.user_id user2
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 r1.user_id, r2.user_id
HAVING count(*) >= 5;
演示: - &gt; http://www.sqlfiddle.com/#!2/7a9b7/3
----编辑----
要按匹配数量订购用户,请使用以下查询:
SELECT r1.user_id user1, r2.user_id user2,
count(*) number_of_matches
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 r1.user_id, r2.user_id
HAVING count(*) >= 5
ORDER BY number_of_matches DESC
-- you may also use:
-- ORDER BY COUNT(*) DESC
;
演示 - &gt; http://www.sqlfiddle.com/#!2/7a9b7/8