1

私は投票システムを持っており、投票の作成者に電子メールを送信できるように、どの投票が完了したかを検出するMySQLのクエリを作成しようとしています。投票は、(1)時間がなくなると(すでに簡単に解決できます)、または(2)すべての投票者が投票したときに完了します。

これに関連する2つのテーブルがあります。最初のテーブルは「votes」で、各投票が記述され、一意の「vote_id」があります。2番目のテーブルは「チケット」です。投票の作成時に、各参加者はチケットを作成します(これにはいくつかの認証情報が含まれています)。各チケットには、「votes」テーブルのフィールドに対応する「vote_id」フィールドがあります。したがって、基本的に、人々が投票すると、対応するチケットがチケットテーブルから削除されます。これは、特定の「vote_id」の「チケット」の行数が、投票しなかった人の数に対応することを意味します。

最初に私はこのようなことをしに行きました:

SELECT votes.vote_id
FROM votes, tickets
WHERE votes.vote_id=tickets.vote_id
AND (votes.completion_timestamp < NOW())
HAVING (COUNT(tickets.vote_id) = 0)

しかし、その後、「votes.vote_id=tickets.vote_id」行のために...未処理のチケットがない投票は無視されることを意味することに気づきました。これを行うには多くの非効率的な方法を考えることができますが、MySQLでこれを行う方法があると思いますか?

質問の一般化された要約:共通のフィールドFを持つ2つのテーブルAとBが与えられた場合、Bに存在しないAのすべてのFを見つけるにはどうすればよいですか?

4

2 に答える 2

3

MySQLでこれを効率的に行うには、次のトリックが必要です。

select v.*
from votes v
where votes.completion_timestamp < NOW() and
      not exists (select 1 from tickets t where t.vote_id = v.vote_id)

あなたが持っているSQLは完全に正しくありません。次のバージョンが機能するはずです。

SELECT distinct votes.vote_id
FROM votes left outer join
     tickets
     on votes.vote_id=tickets.vote_id
where votes.completion_timestamp < NOW()) and
      tickets.vote_id is null 

サブクエリでのEXISTSとINの使用については、MySQLのドキュメント(http://dev.mysql.com/doc/refman/5.0/en/subquery-optimization-with-exists.html)で詳しく説明されています。左外側の結合との違いは、2つのことにあります。戦略に参加し、I/Oを増やします。

JOIN戦略が左アウタージョインの違いかどうかはわかりません。EXISTSバージョンより悪くないはずだと思います。ただし、2番目のポイントは、左外部結合が、行数を増やす可能性のある出力セットを作成することです。EXISTSバージョンはこれを行うことができません。

ドキュメントを読んだ後、次のことがさらに効率的になる可能性があります。

select v.*
from votes v
where votes.completion_timestamp < NOW() and
      not exists (select 1 from tickets t where t.vote_id = v.vote_id limit 1)

制限は、遭遇した最初の行を超える評価を短絡させる必要があります。

于 2012-08-22T15:23:45.903 に答える
2

このようなものはあなたが期待する結果を返します:

select votes.vote_id
from votes
    left outer join tickets on votes.vote_id = tickets.vote_id
where tickets.ticket_id is null or votes.completion_timestamp < NOW()

tickets.ticket_idこれは、がテーブルの主キーであり、ticketsNULLにすることはできないことを前提としています。このクエリは、 NULLでなければならない
条件で、投票からチケットへの左外部結合を実行することにより、この事実を利用します。これは、その投票tickets.ticket_idのテーブルにチケットが1つもない場合にのみ発生します。tickets

于 2012-08-22T15:23:10.803 に答える