2

3 つの 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

単一のクエリで取得する必要があります:

  • 投票があるかどうかに関係なく、常にすべての機能
  • 投票がなくても、投票数に関係なく、各機能は 1 回だけリストする必要があります。
  • リストされた各機能の投票数
  • 現在ログインしているユーザーがリスト内の現在の機能に投票した場合の特別なマーク - たとえば、ユーザー 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 に投票した場合、この例ではユーザー 4 がログインしているため、ユーザー 4 には関係がないため、まだ NULL です。

問題は次のとおりです。

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 の上記のクエリはすべて、ユーザー ID に関係なく、5 つの機能すべてを出力する必要があります。したがって、他の人が機能に投票した場合、投票がない場合、または現在のユーザーが機能に投票した場合でも、すべての機能を表示するようにクエリを何らかの方法で変更する必要があります。

4

2 に答える 2

2

これはそれを行う必要があります:

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ではなく、おそらく最適化の余地もあります

于 2013-03-20T04:41:42.560 に答える
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
于 2013-03-20T03:39:07.847 に答える