计算逗号分隔的值并获得另一个的总和

时间:2013-09-30 11:27:17

标签: mysql

我有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)

谢谢!

3 个答案:

答案 0 :(得分:2)

您应该normalize您的数据,而不是以逗号分隔值存储值,这将更容易在查询中处理。只需添加一个新列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;

答案 1 :(得分: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

答案 2 :(得分: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;

<强> SAMPLE FIDDLE