我有一个名为matches
的表,用户可以在其中决定自己喜欢的人。例如:
+----+----------+----------+
| id | users_id | match_id |
+----+----------+----------+
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 2 | 1 |
| 4 | 3 | 2 |
+----+----------+----------+
如上所示,第一个用户选择了用户2
和3
,第二个用户选择了1
,第三个用户选择了2
。现在,第一用户和第二用户是相互的(demo in fiddle,适用于v5.5)。
...以及万一其他互联网中断了...
CREATE TABLE watched (
`id` INTEGER,
`users_id` INTEGER,
`watched` VARCHAR(6)
);
INSERT INTO watched
(`id`, `users_id`, `watched`)
VALUES
('1', '1', 'movie1'),
('2', '1', 'movie2'),
('3', '1', 'movie3'),
('4', '2', 'movie2'),
('5', '2', 'movie1'),
('6', '3', 'movie1'),
('7', '3', 'movie5'),
('8', '3', 'movie4');
CREATE TABLE users (
`id` INTEGER,
`name` VARCHAR(355),
`email` VARCHAR(355)
);
INSERT INTO users
(`id`, `name`, `email`)
VALUES
('1', 'name1', 'email1@mail.com'),
('2', 'name2', 'email2@mail.com'),
('3', 'name3', 'email3@mail.com');
CREATE TABLE profile (
`id` INTEGER,
`users_id` INTEGER,
`about` VARCHAR(355)
);
INSERT INTO profile
(`id`, `users_id`, `about`)
VALUES
('1', '1', 'something about me'),
('2', '2', 'something about me'),
('3', '3', 'something about me');
CREATE TABLE matches (
`id` INTEGER,
`users_id` INTEGER,
`match_id` VARCHAR(355)
);
INSERT INTO matches
(`id`, `users_id`, `match_id`)
VALUES
('1', '1', '2'),
('2', '1', '3'),
('3', '2', '1'),
('4', '3', '2');
SELECT u1.users_id as me,
u2.users_id as matched,
p.*, u.*
from matches u1
join matches u2 on u2.match_id = u1.users_id
and u2.users_id = u1.match_id
JOIN users u ON u.id=u1.match_id
JOIN profile p ON p.users_id=u1.match_id
where u1.users_id = 1
group by me, matched
现在,存在另一个查询,该查询显示用户与其他用户匹配的电影标题。例如,如果user1
观看了名为movie1
的电影,而另外user2
也观看了movie1
,则它将显示匹配电影的数量(num_movies
),他们的标题以及其他信息,例如用户与该用户的电子邮件等(来自表users
和profile
):
$movies = mysqli_query($connect,
"
SELECT w1.users_id user1
, u.name
, p.*
, u.*
, w2.users_id user2
, COUNT(w2.watched) num_movies
, GROUP_CONCAT(w2.watched ORDER BY w2.watched) movies
FROM watched w1
JOIN watched w2
ON w2.watched = w1.watched
AND w2.users_id != w1.users_id
JOIN users u
ON u.id = w1.users_id
JOIN profile p
ON p.users_id = w1.users_id
WHERE w1.users_id = $id
GROUP
BY user1
, user2
");
while ($row = $movies->fetch_assoc()) {
echo "matched with id {$row['user2']} {$row['num_movies']} times on titles {$row['movies']}\n";
}
或参见demo。
我想这样做,以便上面的查询将仅显示不相互的用户,即不在表matches
中的用户。在我们的情况下,主要用户为user2
,它应仅显示user3
及其匹配的电影标题等。
我该怎么做?
我尝试添加类似
join matches m on m.users_id!=w2.users_id
或m.match_id in(select match_id from matches)!=w2.users_id
,但这些似乎无效。
答案 0 :(得分:1)
一种实现方法是
user
表开始watched
watched
不同于当前用户,并且电影名称相同通过这种方式,您可以获得每个用户和其他任何用户喜欢的所有电影。
剩下的是为每个用户过滤出共同的用户。为此,您可以:
matches
以下是查询:
SELECT u.*, u.id as user1, w2.users_id as user2, count(DISTINCT m.id) AS matched, GROUP_CONCAT(DISTINCT w1.watched ORDER BY w1.watched) AS movies, COUNT(DISTINCT w1.id) AS num_movies
FROM users u
INNER JOIN watched w1 ON w1.users_id = u.id
INNER JOIN watched w2 ON (w1.users_id != w2.users_id) AND w2.watched = w1.watched
LEFT JOIN matches m ON (m.users_id = w1.users_id AND m.match_id = w2.users_id) OR (m.users_id = w2.users_id AND m.match_id = w1.users_id)
WHERE w1.users_id < w2.users_id
GROUP BY user1, user2
HAVING matched < 2