根据朋友选择特定标题'帖子

时间:2015-03-20 15:32:08

标签: php mysql filter group-by

我有一些桌子。

标题

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

任何想法?

1 个答案:

答案 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中有效。