2011-01-03 1 views
0

これは(切り捨てられたクエリ)うまく動作します。 1ヶ月前にそれを修正するための専門家の助言を得ました。 「removeList」:"トリプル参加"? INNER-JOINは、 'WHERE'の後に3番目のテーブルから行を除外する追加クエリを持つことができますか?

SELECT * FROM artWork WHERE art_id in (
    SELECT art_id FROM artWork AS a INNER JOIN userPrefs AS u ON ((
     ((u.media_oil='1' AND a.media_oil='1') OR 
     (u.media_acrylic='1' AND a.media_acrylic='1') OR 
     (u.media_wc='1' AND a.media_wc='1') OR 
     (u.media_pastel='1' AND a.media_pastel='1')) 

     etc, etc........................................ 

    WHERE a.artist_id NOT EXISTS (
     SELECT * FROM removeList AS r 
     WHERE r.artist_id = a.artist_id 
      AND r.user_id ='$user_id') 
      AND a.make_avail='1' 
      AND a.cur_select='1' 
      AND u.user_id='$user_id' 
      AND ((u.pref_painting='1' AND a.pref_painting='1') OR 
       (u.pref_photo='1' AND a.pref_photo='1') OR 
       (u.pref_paper='1' AND a.pref_paper='1') OR 
       (u.pref_print='1' AND a.pref_print='1') OR 
       (u.pref_draw='1' AND a.pref_draw='1') OR 
       (u.pref_sculp='1' AND a.pref_sculp='1') OR 
       (u.pref_install='1' AND a.pref_install='1') OR 
       (u.pref_vid='1' AND a.pref_vid='1') OR 
       (u.pref_public='1' AND a.pref_public='1') OR 
       (u.pref_indef='1' AND a.pref_indef='1')) 
    ) ORDER BY date_submit DESC 

は、しかし、今、私は別の2列(user_idを& artist_id)子テーブルであってもよく、特定の行を除外する必要があります。だから私は「トリプル参加」に相当するものに成功せずにしようとしています(「NOT EXISTS」の周りのコードを探してください):

SELECT * FROM artWork WHERE art_id in (
    SELECT art_id FROM artWork AS a INNER JOIN userPrefs AS u ON ( 
      (((u.media_oil='1' AND a.media_oil='1') OR 
       (u.media_acrylic='1' AND a.media_acrylic='1') OR 
       (u.media_wc='1' AND a.media_wc='1') OR 
       (u.media_pastel='1' AND a.media_pastel='1')) 

       etc, etc........................................ 


    WHERE a.artist_id NOT EXISTS (
     SELECT * FROM removeList AS r 
     WHERE r.artist_id = a.artist_id AND r.user_id ='$user_id' 
    ) 
    AND a.make_avail='1' 
    AND a.cur_select='1' 
    AND u.user_id='$user_id' 
    AND ((u.pref_painting='1' AND a.pref_painting='1') OR 
     (u.pref_photo='1' AND a.pref_photo='1') OR 
     (u.pref_paper='1' AND a.pref_paper='1') OR 
     (u.pref_print='1' AND a.pref_print='1') OR 
     (u.pref_draw='1' AND a.pref_draw='1') OR 
     (u.pref_sculp='1' AND a.pref_sculp='1') OR 
     (u.pref_install='1' AND a.pref_install='1') OR 
     (u.pref_vid='1' AND a.pref_vid='1') OR 
     (u.pref_public='1' AND a.pref_public='1') OR 
     (u.pref_indef='1' AND a.pref_indef='1')) 
    ) ORDER BY date_submit DESC 

は、私があまりにもここに到達していますか?私が見過ごしているより良いアプローチがありますか?ありがとうございます。

+0

ワウ。そして、それは切り捨てられていますか? –

答えて

1

NOT EXISTSは、その前に列名を持つべきではありません。存在しない前にa.artist_idを削除してください。

ので、該当する行は、このクエリを使用しているが、そのもSQLインジェクションを防ぐために、クエリをパラメータ化することを推奨している場所

WHERE NOT EXISTS (
    SELECT * FROM removeList AS r 
    WHERE r.artist_id = a.artist_id AND r.user_id ='$user_id' 
) 

わからないと言うでしょう。

希望すると便利です。

+0

ありがとう!最初のショットに取り組んだ。また、図示されていないfyiは、クエリ全体が変数に保存され、標準的な方法で行を引き出して動的リストにエコーするのに使用される。これは、コードをふるまうようにした2回目のことです。本当にそれを感謝する、ehudokai – artworthy

0

私はこれが答えではないことを知っていますが、私はコメント内にテーブルを置くことができなかったので、ここに入れています。

私はあなたのメディアを保持する余分なテーブルのように感じるし、あなたのデータベース内のものを大幅に単純化するためにここに環境設定が必要です。

media_table 
id, user_id, media_type 

prefs_table 
id, user_id, pref_type 

次に、メディアタイプとprefタイプに関連するアートテーブルのフィールド。

art_table 
media_type, art_type 

このようにして、単純なJOINを使用して、何百もの比較ではなく、関連するレコードを簡単に見つけることができます。

SELECT art.id FROM art JOIN prefs_table ON art.pref_type = prefs_table.pref_type JOIN users ON prefs_table.user_id = users.id WHERE users.id = whatever 

これは、ユーザーの好みのいずれかに一致するアートのすべてのピースをプルアップする単純な例です。もちろん、メディアタイプも同じように同じクエリに簡単に組み込むことができます。

0

dqhendricksで提案されている行に沿って、スキーマについて深刻な作業を行う必要があります。

あなたは3つのテーブルがあります。

  • アートワーク(Art_ID、Artist_ID、...特徴...)
  • ユーザー設定(USER_ID、...特徴...)
  • RemoveList(Artist_IDを、USER_ID)

あなたは、特定のユーザーのユーザーの好みに合わせますが、アーティストがユーザーを嫌うあらゆる芸術作品の一覧を表示したくない場合や、ユーザーがアーティストを嫌う(あるいはその両方芸術作品を一覧表示します) 。

あなたは、そのため、同じような何かを行うことができるはず:

SELECT A.* 
    FROM ArtWork AS A 
    JOIN UserPrefs AS U 
    ON (U.User_ID = ? AND (...ghastly OR'd join conditions...)) 
WHERE A.Artist_ID NOT IN (SELECT R.Artist_ID 
          FROM RemoveList AS R 
          WHERE R.User_ID = ?) 

あなたはWHERE句に結合条件の一部を移動することもできますし、様々な他の変更が、クエリの基本的な構造ArtWorkとUserPrefsのJOINと、NOT IN節付きのWHERE節(NOT EXISTS節として書くことができますが、NOT IN形式は読みやすくなります)となります。

関連する問題