通过一对已知值计算不同的行

时间:2012-05-03 09:56:53

标签: sql join mysqli distinct

我甚至不确定如何说出这个问题。我将提供示例内容并希望输出,我正在寻找一个查询来执行此操作。

假设我的内容名为“已标记”:

content_id | user_id
1          | 1
1          | 2
1          | 3
2          | 1
2          | 3
2          | 4
3          | 2
3          | 3
4          | 1
4          | 2
5          | 1
6          | 1
6          | 4

我在content_ids之间有一个非对称的关系:

master_content_id | slave_content_id
1                 | 2
3                 | 4
5                 | 6

对于每个“master”content_id(1,3和5),我想计算有多少不同的用户标记了主内容或从属内容,但计算将两者标记为单个标志的人 - 这意味着在上面的例子中,content_id = 1由user_id = 1(作为content_id = 1和content_id = 2),user_id = 2(作为content_id = 1),user_id = 3(作为content_id = 1,content_id = 2),并通过user_id = 4(as content_id = 2!)

我想要查询的输出示例是:

content_id | user_count
1          | 4          # users 1, 2, 3, 4
3          | 3          # users 1, 2, 3
5          | 2          # users 1, 4

我不能假设相关的content_ids总是连续的奇数/偶数(即66可以是奴隶58的主人)

我正在使用MySQL并且不介意使用它的SQL扩展(而是查询是ANSI,或者至少可以移植到大多数数据库)

4 个答案:

答案 0 :(得分:3)

以下查询对我有用。

我正在使用带有UNION ALL的子查询来处理您的映射内容等于直接内容。

SELECT master_content_id AS content_id,
       COUNT(DISTINCT user_id) AS user_count
FROM (
  SELECT master_content_id, slave_content_id
    FROM relationship
  UNION ALL
  SELECT master_content_id, master_content_id
    FROM relationship
) r
JOIN flagged f ON ( f.content_id = r.slave_content_id )
GROUP BY master_content_id

<强>结果:

content_id  user_count
         1           4
         3           3
         5           2

答案 1 :(得分:2)

我认为这样的事情对你有用(虽然GROUP_CONCAT是MySQL特有的,但在其他RDBMS中可以实现类似的连接)

SELECT  COALESCE(Master_Content_ID, Content_ID) AS Content_ID,
        COUNT(DISTINCT User_ID) AS Users,
        CONCAT('#Users ', GROUP_CONCAT(DISTINCT User_ID ORDER BY User_ID)) AS UserList
FROM    Flagged
        LEFT JOIN MasterContent
            ON Content_ID = Slave_Content_ID
GROUP BY COALESCE(Master_Content_ID, Content_ID)

示例SQL小提琴:http://www.sqlfiddle.com/#!2/d09be/2

输出:

CONTENT_ID  USERS   USERLIST
1           4       #Users 1,2,3,4
3           3       #Users 1,2,3
5           2       #Users 1,4

答案 2 :(得分:1)

从给出的样本中,这是否能完成这项工作(我没有MySQL可供测试)?

SELECT 
    ms.master_content_id,
    (SELECT COUNT(DISTINCT f.user_id) FROM flagged f WHERE
                      f.content_id = ms.slave_content_id OR
                      f.content_id = ms.master_content_id)
FROM
    master_slave ms

拥有DISTINCT会更好,但我看不到它的方法。

答案 3 :(得分:1)

SELECT master_content_id      AS content_id
     , COUNT(*)               AS user_count
     , GROUP_CONCAT(user_id)  AS flagging_users
FROM 
  ( SELECT r.master_content_id 
         , f.user_id
    FROM relationship AS r
      JOIN flagged AS f
        ON f.content_id = r.master_content_id
  UNION 
    SELECT r.master_content_id
         , f.user_id
    FROM relationship AS r
      JOIN flagged AS f
        ON f.content_id = r.slave_content_id
  ) AS un
GROUP BY master_content_id