我有一些桌子。
标题
id| title
1 | Cars
2 | Computers
3 | Phones
4 | Tvs
输入
id | title_id | user_id | entry | time
1 | 1 | 12 | entry-01 | 1
2 | 2 | 11 | entry-02 | 2
3 | 3 | 12 | entry-03 | 3
4 | 2 | 11 | entry-04 | 4
5 | 3 | 11 | entry-05 | 5
6 | 4 | 12 | entry-06 | 6
7 | 4 | 13 | entry-07 | 7
8 | 4 | 11 | entry-08 | 8
9 | 1 | 10 | entry-09 | 9
10 | 2 | 12 | entry-10 | 10
用户
id | username
10 | user-1
11 | user-2
12 | user-3
13 | user-4
朋友
id | user_id | friend_id
1 | 10 | 12
2 | 11 | 12
3 | 12 | 10
4 | 10 | 11
我需要根据朋友过滤标题'条目和排序结果(entry.time)desc。我还需要在列表中显示朋友姓名和计数(条目)。
user_id = 10过滤的预期结果是:
结果
1 | Computers | user-3, user-2(2)
2 | Tvs | user-2, user-3
3 | Phones | user-2, user-3
4 | Cars | user-3
任何想法?
答案 0 :(得分:1)
这个问题很复杂,但是如果你养成将问题分解成小块的习惯,你会很快就会遇到。为什么不从获得用户ID 10的所有朋友开始?我们可以这样做:
SELECT CASE WHEN user_id = 10 THEN friend_id
WHEN friend_id = 10 THEN user_id END AS userFriends
FROM friends
GROUP BY userFriends
HAVING userFriends IS NOT NULL;
请注意case语句的使用,因为user_id 10可以位于两列中的任何一列中。我使用GROUP BY以防用户/朋友对出现多次(例如10和12),并检查非null以删除与案例不匹配的行。
现在你已经拥有了这些,你可以将它与条目和标题表一起加入,以获得你需要的信息。只需添加一些聚合以获取每个用户对标题的条目数:
SELECT t.title, u.userName, COUNT(*) AS numEntries
FROM titles t
LEFT JOIN entry e ON e.title_id = t.id
JOIN users u ON u.id = e.user_id
JOIN(
SELECT
CASE WHEN user_id = 10 THEN friend_id
WHEN friend_id = 10 THEN user_id END AS userFriends
FROM friends
GROUP BY userFriends
HAVING userFriends IS NOT NULL) f ON f.userFriends = u.id
GROUP BY t.title, u.userName;
匹配您的格式将非常棘手。通常情况下,您可以使用GROUP_CONCAT()
来获取以逗号分隔的列表,但第一个列表中会显示user3, user2, user2
之类的内容。为了解决这个问题,我建议在select语句中编写一个CONCAT()来修改上面的查询,以获得每个用户一侧的条目数。此外,使用另一个CASE语句,以便只有在COUNT(*)大于1时才会发生这种情况:
SELECT t.title,
CASE WHEN COUNT(*) > 1 THEN
CONCAT(u.userName, ' (', COUNT(*), ')')
ELSE
u.userName
END AS numEntries
FROM titles t
LEFT JOIN entry e ON e.title_id = t.id
JOIN users u ON u.id = e.user_id
JOIN(
SELECT
CASE WHEN user_id = 10 THEN friend_id
WHEN friend_id = 10 THEN user_id END AS userFriends
FROM friends
GROUP BY userFriends
HAVING userFriends IS NOT NULL) f ON f.userFriends = u.id
GROUP BY t.title, u.userName;
现在,我会在该查询上预先形成GROUP_CONCAT():
SELECT tmp.title, GROUP_CONCAT(tmp.userEntries) AS friendEntries
FROM(
SELECT t.title,
CASE WHEN COUNT(*) > 1 THEN
CONCAT(u.userName, ' (', COUNT(*), ')')
ELSE
u.userName
END AS userEntries
FROM titles t
LEFT JOIN entry e ON e.title_id = t.id
JOIN users u ON u.id = e.user_id
JOIN(
SELECT
CASE WHEN user_id = 10 THEN friend_id
WHEN friend_id = 10 THEN user_id END AS userFriends
FROM friends
GROUP BY userFriends
HAVING userFriends IS NOT NULL) f ON f.userFriends = u.id
GROUP BY t.title, u.userName) tmp
GROUP BY tmp.title;
我为冗长的回应道歉(虽然我想要清楚并涵盖所有)。如果你已经达到了这一点,你会很高兴地知道它在SQL Fiddle中有效。