2011-08-09 14 views
3

私は "システムのデフォルト"と "ユーザーの好み"を持っている設定モジュールの。
個人設定/ユーザ設定が保存されていない場合は、代わりにシステムのデフォルト値を使用してください。ここでMysqlは、1つのクエリとして、行が存在しない場合、他のクエリを実行

私のシステム環境設定テーブルです:

mysql> desc rbl; 
+-------------+---------------------+------+-----+---------+-------+ 
| Field  | Type    | Null | Key | Default | Extra | 
+-------------+---------------------+------+-----+---------+-------+ 
| id   | varchar(3)   | NO | PRI |   |  | 
| rbl_url  | varchar(100)  | NO |  |   |  | 
| description | varchar(100)  | NO |  |   |  | 
| is_default | tinyint(1) unsigned | YES |  | 1  |  | 
+-------------+---------------------+------+-----+---------+-------+ 
4 rows in set (0.00 sec) 
システムのprefsから

データ例:システムのデフォルトのため

mysql> select * from rbl; 
+----+----------------------+------------------------------+------------+ 
| id | rbl_url    | description     | is_default | 
+----+----------------------+------------------------------+------------+ 
| 1 | sbl-xbl.spamhaus.org | Spamhaus SBL-XBL    |   1 | 
| 2 | pbl.spamhaus.org  | Spamhaus PBL     |   1 | 
| 3 | bl.spamcop.net  | Spamcop Blacklist   |   1 | 
| 4 | rbl.example.com  | Example RBL - not functional |   0 | 
+----+----------------------+------------------------------+------------+ 

...と問合せ:

mysql> SELECT rbl_url FROM rbl WHERE is_default='1'; 
+----------------------+ 
| rbl_url    | 
+----------------------+ 
| sbl-xbl.spamhaus.org | 
| pbl.spamhaus.org  | 
| bl.spamcop.net  | 
+----------------------+ 
3 rows in set (0.01 sec) 

これまでのところは良い。 OK。今、私は、ユーザーの好みのテーブルを必要とする、と私はこの思い付いた:(。FYI - A「ユーザー」が「domain_idに」によって表される)

mysql> desc rbl_pref; 
+-----------+-----------------------+------+-----+---------+----------------+ 
| Field  | Type     | Null | Key | Default | Extra   | 
+-----------+-----------------------+------+-----+---------+----------------+ 
| id  | mediumint(8) unsigned | NO | PRI | NULL | auto_increment | 
| domain_id | mediumint(8) unsigned | NO |  | NULL |    | 
| rbl_id | tinyint(1) unsigned | NO |  | NULL |    | 
+-----------+-----------------------+------+-----+---------+----------------+ 
3 rows in set (0.00 sec) 

のは誰特定のユーザーの設定を表示してみましょうパーソナライズされた設定は保存された:

mysql> select * from rbl_pref where domain_id='2277'; 
+----+-----------+--------+ 
| id | domain_id | rbl_id | 
+----+-----------+--------+ 
| 4 |  2277 |  1 | 
| 5 |  2277 |  2 | 
| 6 |  2277 |  4 | 
+----+-----------+--------+ 
3 rows in set (0.00 sec) 

...再び、しかし、単純な形式で:

mysql> SELECT rbl.rbl_url FROM rbl_pref,rbl 
     WHERE rbl_pref.rbl_id=rbl.id AND domain_id='2277'; 
+----------------------+ 
| rbl_url    | 
+----------------------+ 
| sbl-xbl.spamhaus.org | 
| pbl.spamhaus.org  | 
| rbl.example.com  | 
+----------------------+ 
3 rows in set (0.00 sec) 

.. ここまでは順調ですね。ユーザーが設定を保存している場合、結果が見つかります。

今の問題の例は、ユーザー1999にはカスタム設定がありません。 "空のセット"の代わりに、システムのデフォルトを設定します。

mysql> SELECT rbl.rbl_url FROM rbl_pref,rbl 
     WHERE rbl_pref.rbl_id=rbl.id AND domain_id='1999'; 
Empty set (0.00 sec) 

私は非常によく似た質問を見つけることに興奮しました:しかし日の試行錯誤とドキュメントのレビューのカップルの後、私はここに上でその答えを変換できませんでした。 mysql if row doesn't exist, grab default value を。

上記の質問と同様に、これは単一のMySQLクエリとして実行する必要があります。私はPHPからこのクエリを実際には作成していませんが、Eximマクロから(そしてそれは非常に厄介な言語です...私はここでしようとすると、変数の割り当てとして "1ライナー"をフィードするのに最適です..)

UPDATE:下記の@Biff McGriffによって提案されたUNIONクエリの1つのタイプを試しました。テーブルには、私のコメントの返信には表示されませんでしたので、ここでは、再びです:

mysql> SELECT rbl.rbl_url FROM rbl_pref,rbl 
     WHERE rbl_pref.rbl_id=rbl.id AND domain_id='2277' 
     UNION SELECT rbl_url FROM rbl WHERE is_default='1'; 
+----------------------+ 
| rbl_url    | 
+----------------------+ 
| sbl-xbl.spamhaus.org | 
| pbl.spamhaus.org  | 
| rbl.example.com  | 
| bl.spamcop.net  | 
+----------------------+ 
4 rows in set (0.00 sec) 

あなたが上見ることができるように、利用者2277は3(bl.spamcop.net)をrbl_idにオプトインしていないが、それが現れていますいずれかの方法。

私のUNIONクエリは、と思われる結果セットを組み合わせています。だから、user_prefはグローバルなデフォルトに "加えて"機能し、私はクエリの半分に一致する結果セットが得られると思っていました。

私の質問は今、「どちらかの結果セット」(UNIONのいずれかの側のサブクエリ)としてこれを解決する方が良いでしょうか(または可能でしょうか)。または、本当にrbl_prefに新しいフィールドが必要ですか。たとえば、 "enabled"と呼ばれています。後者はもっと正しいと思われます - オプトインまたはオプトアウトを明示的に指定するには、rbl_prefに何かが必要です(暗黙の "rf_id = 3でない"

更新:すべてのセット、感謝@Imre L、および他の人。私はこの例を通して何かを学びました。

+0

は、あなたが左に参加しようとしたことがありますか? – Dor

答えて

1

注:domain_idを2か所に入力する必要があります。

SELECT rbl.rbl_url FROM rbl 
    JOIN rbl_pref ON rbl_pref.rbl_id=rbl.id AND domain_id=2277 
UNION 
SELECT rbl.rbl_url FROM rbl 
WHERE rbl.is_default 
    AND NOT EXISTS (SELECT 1 FROM rbl_pref WHERE domain_id=2277 LIMIT 1) 
; 

今1またはUNIONの他の側面は、あなたがまたrbl.idためvarchar(3)しかしtinyintがあまりにもされている整数 とrbl_pref.rbl_idとして好ましいと同じタイプのいくつかの並べ替えを使用しないでくださいimpossible where

で離れて最適化されます小さい

の整数フィールドを比較するときは、const34の周りに'または"を使用しないでください。 nts整数。 ほとんどの場合whithを取り除くことができますが、mysqlオプティマイザを混乱させることがあります。

はまた、最適なパフォーマンスと一貫性のために私はあなたがインデックスを追加提案:

ALTER TABLE rbl_pref 
    ADD UNIQUE INDEX ux_domain_rbl (domain_id, rbl_id); 
+0

答え、説明、および最適化のヒントを3回感謝します。私はこれを前払いしようとします。私はMySQLのドキュメントをよく見直して、なぜこれが正確に機能するのか知っています。 rbl.idのvarcharを正しく把握できます。これは既存のテーブルであり、私はそれを修正して残りの部分を更新します。 rbl.idフィールドとrbl_pref.rbl_idフィールドは、両方とも符号なしTINYINTとしてOKです... rblは、ユーザーではなく、数人のエンジニアによって厳重に管理されています。 255の限界までは今まで必要とされていたものをはるかに超えています。しかし警告のためにありがとう、それは小さすぎるかもしれません。 –

3

左結合を使用できるようにしてから、coalesceの既定のフィールドを持つユーザーのフィールドを使用する必要があります。

+0

このヒントは興味深いと思う - 私はジョインについて読んでいて、それは正しい方向であるように聞こえる...しかし、私はちょうどまだ答えにあなたのヒントを翻訳することはできません。私はしかし、継続します! :-) –

+0

幸運、@ScottInNH。 –

関連する問題