2

我有 2 张桌子;用户和意见。下面的示例架构和数据

users table
---------------------------------
userid
  1
  2
  3
  4
  5

opinions table
---------------------------------
opinionid   |   points   |   yes   |   no
    1             5         1,2,3      4,5
    2             5         1,3,5      2,4
    3            10         1,2,4      3,5
    4            10         1,4,5      2,3
    5            15           1      2,3,4,5

* the yes and no columns contains comma-delimited userids

期望的结果:按用户 ID 分组,按点排序,是,否

userid   |   points   |   yes   |   no
  1            45          5         0
  4            20          2         3
  2            15          2         3
  5            15          2         3
  3            10          2         3

Summary: for each userid, sum(points), count(yes), count(no)

谢谢!

4

3 回答 3

2

您应该规范化您的数据,而不是将值存储为逗号分隔,这将更容易在查询中处理。只需添加一个新列user_id作为外键,并添加一个列作为标志YesOrNo,然后为每个意见输入用户 ID,并为每个设置一个标志值 0 或 1。


现在,您可以使用该FIND_IN_SET功能来做您正在寻找的事情,如下所示:

SELECT
  userid,
  sum(CASE WHEN type = 'yes' THEN points ELSE 0 END), 
  SUM(CASE WHEN type = 'yes' THEN 1 ELSE 0 END) AS Yes,
  SUM(CASE WHEN type = 'no' THEN 1 ELSE 0 END) AS No
FROM
(
  SELECT 
    o.opinionid,
    o.points,
    'yes' AS type,
    u.userid
  FROM options AS o
  INNER JOIN users AS u ON FIND_IN_SET(u.userid, o.yes) <> 0
  UNION
  SELECT
    o.opinionid,
    o.points,
    'no' AS type,
    u.userid
  FROM options AS o
  INNER JOIN users AS u ON FIND_IN_SET(u.userid, o.no) <> 0
) AS t
GROUP BY userid;
于 2013-09-30T11:48:55.187 回答
0

这是一个简单而优雅的解决方案

    select userid, 
    sum(if(FIND_IN_SET(userid, yes.yes)>0, yes.points, null)) as points, 
    count(if(FIND_IN_SET(userid, yes.yes)>0,1,null)) as yes, 
    count(if(FIND_IN_SET(userid, yes.no)>0,1,null)) as no

        from users 
        left join opinions as yes 
        on (FIND_IN_SET(userid, yes.yes)>0 or FIND_IN_SET(userid, yes.no)>0)
    group by userid
于 2013-09-30T11:52:01.520 回答
0
SELECT yestbl.userid, total, yes, no
FROM
(SELECT userid,
SUM(oyes.points) total,
COUNT(FIND_IN_SET(u.userid,oyes.`yes`)) as `yes`
FROM users u LEFT JOIN
opinions oyes
ON FIND_IN_SET(u.userid,oyes.`yes`)
GROUP BY userid) yestbl
LEFT JOIN
(SELECT userid,
COUNT(FIND_IN_SET(u.userid,ono.`no`)) as `no`
FROM users u LEFT JOIN
opinions ono
ON FIND_IN_SET(u.userid,ono.`no`)
GROUP BY userid) notbl
ON yestbl.userid = notbl.userid
GROUP BY yestbl.userid
ORDER BY total desc;

样品小提琴

于 2013-09-30T12:46:57.903 回答