我有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)
谢谢!
答案 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 强>