2013-03-20 39 views
2

我有3个MySQL表:计票,如果用户在MySQL表中投

功能表:

id name 
---------- 
1 feature 1 
2 feature 2 
3 feature 3 
4 feature 4 
5 feature 5 

投票表:

userid featureid 
---------------- 
1  1 
1  2 
1  3 
1  4 
2  1 
2  2 
2  3 
2  4 
3  1 
3  2 
3  3 
4  1 

用户表:

id name 
-------- 
1 John 
2 Alice 
3 Bob 
4 Mark 
5 Jane 
6 Mary 
7 Ann 

我需要在单个查询中获取:

  • 总是所有功能,无论它们有投票或不
  • 每个功能必须只列出一次不管票数的,即使它没有票
  • 的投票为每个特征列出
  • 如果当前登录的用户投票选择列表中的当前功能,则为特殊标记 - 例如,如果用户3已登录,则列出所有用户的投票数的所有功能,如果用户3投票选择某些功能,则有专门的字段表示其投票或如果他没有,则为NULL(其他数据来自投票表也必须包含,因此它需要被LEFT JOINED)

到目前为止,我这样做:

SELECT *,(SELECT COUNT(*) FROM votes WHERE votes.featureid=features.id) AS "votecnt" 
FROM features 
LEFT JOIN votes ON votes.featureid=features.id 
LEFT JOIN users ON users.id=votes.userid 
GROUP BY features.id 

它列出了所有功能,但没有特殊的领域,如果用户3投票。我尝试了IF,各种WHERE条件以及经过很多尝试......都没有想法。

所需的输出可能是这样的:

features.id features.name votes.userid votes.otherfields users.id users.name 
    1   feature 1   4    -    4  Mark 
    2   feature 2  NULL   -    NULL  NULL 
    3   feature 3  NULL   -    NULL  NULL 
    4   feature 4  NULL   -    NULL  NULL  
    5   feature 5  NULL   -    NULL  NULL 

所有特性列表,只有那些用户4投有其他的连接表填写,其余的则只是NULL。如果其他人投票支持功能2它仍然是NULL,因为它是没有相关性,为用户4,因为在这个例子中用户4登录

这里的问题是:

http://sqlfiddle.com/#!2/c3d10/3

http://sqlfiddle.com/#!2/c3d10/4

http://sqlfiddle.com/#!2/c3d10/5

http://sqlfiddle.com/#!2/c3d10/6

http://sqlfiddle.com/#!2/c3d10/7

在SQLFiddle中,所有上述查询都应该输出所有5个功能,而不管用户标识符如何。因此,查询必须以某种方式进行修改才能显示所有功能 - 即使其他人投票选择了功能,或者如果没有投票或当前用户投票选择功能。

+3

你能以表格形式显示你想要的结果吗? – 2013-03-20 03:18:44

+1

sqlfiddle.com和您想要的结果 – Martin 2013-03-20 03:26:01

+1

'features.id = 4'仅由一个人投票,现在如果某个功能被多个用户投票,那么'votes.userid'看起来会怎样? CSV上的ID?如果'users.id = 3'登录了怎么办?结果是什么? – 2013-03-20 03:30:27

回答

1

我想你要求返回所有功能,返回所有计数,但只有用户信息表示他们投票支持该功能。

我得到你正在寻找,如果你指定用户ID

select f.id 
, f.name 
, u.id 
, u.name 
, v.votecnt 
from features f 
left join (select featureid, COUNT(userid) votecnt from votes group by featureid) v on v.featureid = f.id 
left join votes v1 on v1.featureid = f.id and v1.userid = 4 
left join users u on u.id = v1.userid 

我选择指定左侧内的用户ID的结果加入到票。任何地方,它限制了返回的行数。

结果:

1 feature 1 4 Mark 4 
2 feature 2 NULL NULL 3 
3 feature 3 NULL NULL 3 
4 feature 4 NULL NULL 2 
5 feature 5 NULL NULL NULL 

实施例与 “鲍勃”

select f.id 
, f.name 
, u.id 
, u.name 
, v.votecnt 
from features f 
left join (select featureid, COUNT(userid) votecnt from votes group by featureid)v on v.featureid = f.id 
left join votes v1 on v1.featureid = f.id and v1.userid = 3 
left join users u on u.id = v1.userid 

结果:

1 feature 1 3 Bob 4 
2 feature 2 3 Bob 3 
3 feature 3 3 Bob 3 
4 feature 4 NULL NULL 2 
5 feature 5 NULL NULL NULL 
+0

在您的查询中,如果您使用ID = 3,4或5,则不会列出所有功能。所有功能必须只列出一次,无论用户是谁投票和谁使用的。 - 看看http://sqlfiddle.com/#!2/c3d10/10 – Coder12345 2013-03-20 03:52:25

+0

我的其他评论没有意义。我能够获得您正在查找的结果,并删除了之前不正确的SQL,并只发布了工作代码和结果。使用左连接内的用户标识符做了这个窍门。 – Vinnie 2013-03-20 13:08:59

+1

实际上,这整个问题是一个混乱和复杂的解释,但你的查询现在确实产生所需的结果,它看起来很简单。谢谢 - 出色的工作。 – Coder12345 2013-03-20 16:38:55

1

这应该这样做:

SELECT tmp1.id, name, votecnt, user_id, user_name FROM 
(SELECT *,(SELECT COUNT(*) FROM votes WHERE votes.featureid=features.id) AS "votecnt" FROM features) as tmp1 
LEFT JOIN (SELECT features.id as feature_id, users.id as user_id, users.name as user_name FROM features 
JOIN votes ON votes.featureid=features.id 
JOIN users ON users.id=votes.userid 
WHERE users.id=3) as tmp2 on tmp1.id = tmp2.feature_id 

可能它不是最漂亮的sql,并且最有可能还有优化空间

+0

感谢您的回答,这是很好的工作,它确实产生所需的输出。但是,我接受了Vinnie的答案,因为他的版本看起来更加优化,并且在SQL执行计划中需要少两步,因此可能会更快一些。感谢您的工作成果和付出的努力,非常感谢! – Coder12345 2013-03-20 16:36:22