2011-08-13 11 views
3

私は、このいわゆる「ポスト」のように見える1つのSQLテーブルがあります。MySQL:別のテーブルから2つのカウントを使用して注文しますか?

id | user 
-------------------------------- 
0 | tim 
1 | tim 
2 | bob 

そして「ポスト」テーブル内のポストにupvotesかdownvotesのいずれかを格納する「投票」と呼ばれる別:

id | postID | type 
-------------------------------- 
0 | 0  | 0 
1 | 2  | 1 
2 | 0  | 1 
3 | 0  | 1 
4 | 3  | 0 

この表の 'type'は、downvoteの場合は0、upvoteの場合は1です。

「tim」の投稿の投稿数(upvotes - downvotes)で投稿を並べる方法を教えてください。

+0

、ティムの最初のポスト( 'idが= 0 ')2 upvotesと1つのdownvoteを持っているので、それはので、彼の第2のポスト(' idは= 1')いずれかの票を持っていませんが、スコアは1です。スコアはゼロです。したがって、これらが選択されている場合( 'SELECT * FROM posts WHERE user = 'tim' ORDER BY DESC')、投稿テーブルに新しいフィールドを追加せずに何らかの方法でスコアを並べることができます。 – Tomas

答えて

3
SELECT 
    p.id, 
    p.user, 
    SUM(v.type * 2 - 1) AS votecount 
FROM posts p 
    LEFT JOIN votes v ON p.id = v.postID 
WHERE p.user = 'tim' 
GROUP BY p.id, p.user 
ORDER BY votes DESC 

UPDATEからpvについて説明します。このクエリで

pvエイリアスそれぞれのpostsvotesあります。エイリアスは本質的に代替名であり、それを宣言するステートメント(この場合はSELECTステートメント)のスコープ内でのみ定義されます。テーブルにはエイリアスだけでなく、カラムも設定できます。このクエリでは、votecountSUM(v.type * 2 - 1)式で表される列のエイリアスです。しかし、現在私たちはテーブルについてしか話していません。

テーブルエイリアスについて説明する前に、なぜidではなく、posts.idのようにテーブル名にプレフィックスを付ける必要があるのか​​を簡単に説明します。基本的に、クエリが複数のテーブルを参照する場合、この場合のように、常にカラム名にそれぞれのテーブル名を接頭辞として付けることは非常に便利です。こうすることで、古いスクリプトを再訪しているときに、参照されているテーブルの構造を調べなくても、どのカラムがどのテーブルに属しているかをいつでも知ることができます。またそれはである必要があります。テーブル参照を含めると、それが省略されたときに、そのテーブルが属するテーブルが不明確になります。 (この場合、各テーブルには、自分のidを持っているので、曖昧な状況を作り出すんpostsテーブルを参照せずid列を参照。)

は今、大規模で複雑なクエリは、完全書き出す際に読み取ることが難しいかもしれ列名の前にテーブル名。これは、(短い)エイリアスが便利なところです:質問は読みやすく理解しやすくなりますが、私はすでにすべての人がその意見を共有しているわけではないことを学んだので、あなた自身で判断する必要があります。this questionは同じ長い名前のテーブル参照を持つものと短いものを付けたものの1つと、エイリアスが適切でない理由(回答の1つのコメントの中での意見)があります。

とにかく、この特定のクエリで短いテーブルエイリアスを使用すると、より複雑なステートメントほど有益ではない場合があります。クエリが複数を参照するときはいつもテーブルのエイリアシングに慣れています。

This MySQL documentation articleには、MySQLのエイリアステーブルの公式構文が含まれています(実際には標準SQLと同じです)。

+0

投票値 - かわいい、素敵な –

+0

@Derek:ありがとう。しかし、他のタイプが存在する場合や表示される場合は、破損する可能性があります。しかし、より伝統的な(そして信頼できる)CASE/IF()メソッドの代わりとして、そのままそのまま残しています。 –

+0

@Andiry M:申し訳ありませんが、私はSQLを勉強しています。あなたがそれらの一文字が何であるかを明確にすることができれば、本当に感謝します。(pとv) ?私をチュートリアルにリンクさせたり、彼らの名前を教えてください。ありがとう。 – Tomas

1

は、試験されたが、動作するはずはない:

select post.id, sum(if(type = 0, -1, 1)) as score 
from posts join votes on post.id = votes.postID 
where user = 'tim' 
group by post.id 
order by score 

あなたはSO同意することを計画していますか? ;-)

1

編集:私はサブクエリを削除するので、mysqlでは不要です。元のクエリは移植性がありましたが、mysqlでは不要です。基本的に

select 
    p.id, SUM(case 
       when v.type = 0 then -1 
       when v.type = 1 then 1 
       else 0 end) as VoteCount 
from 
    posts p 
    left join votes v 
     on p.id = v.postid 
where 
    p.[user] = 'tim' 
group by 
    p.id 
order by 
    VoteCount desc 
+0

こんにちはderek、なぜサブクエリですか? – TMS

+0

私はそれを更新しました - 私はもっとmssqlに精通していますので、移植可能なものを書きました。更新されたクエリは、mysqlに合わせて調整する必要があります。 –

+0

@Derek:SQL ServerがORDER BYでもエイリアス参照をサポートしていることはおそらく認識していません。 +1古き良きクロスプラットフォームのCASEメソッドでは '@' - 名前はおそらく '通常の'ものに置き換えてください。 –

関連する問題