"Тройное соединение" ??Может ли INNER-JOIN иметь запрос add'l после 'WHERE' для исключения строк из 3-й таблицы? - PullRequest
0 голосов
/ 04 января 2011

Хорошо, этот (усеченный запрос) работает нормально. Месяц назад получил совет специалиста, чтобы это исправить.

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

Но теперь мне нужно исключить некоторые строки, которые могут быть в другой дочерней таблице с двумя столбцами (user_id & artist_id): 'removeList'. Поэтому я безуспешно пытаюсь понять, что означает «тройное соединение» (ищите код «НЕ СУЩЕСТВУЕТ»):

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

Я слишком далеко захожу? Есть ли лучший подход, который я пропускаю? Спасибо всем.

Ответы [ 3 ]

1 голос
/ 04 января 2011

NOT EXISTS не должно иметь имени столбца перед ним.удалите a.artist_id до того, как не существует.

Таким образом, соответствующая строка скажет

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

Не уверен, где вы используете этот запрос, но также рекомендуется параметризовать ваши запросыпредотвратить инъекции sql.

Надеюсь, это поможет!

0 голосов
/ 04 января 2011

Вам необходимо проделать серьезную работу над своей схемой в соответствии с рекомендациями dqhendricks .

У вас есть 3 таблицы:

  • ArtWork (Art_ID, Artist_ID, ... характеристики ...)
  • UserPrefs (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 и другие различные изменения, но базовой структурой запроса будет JOINArtWork и UserPrefs и предложение WHERE с предложением NOT IN (которое можно написать как предложение NOT EXISTS, но я думаю, что формулировку NOT IN легче читать).

0 голосов
/ 04 января 2011

я знаю, что это не ответ, но я не смог разместить таблицу в комментариях, поэтому я помещаю ее сюда.

я чувствую, что для хранения ваших медиафайлов необходимы дополнительные таблицы и префы, чтобы значительно упростить работу вашей базы данных.

media_table
id, user_id, media_type

prefs_table
id, user_id, pref_type

Затем поля в вашей художественной таблице, которые соответствуют типу носителя и типу префа.

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

Это упрощенный пример, который раскрыл бы все виды искусства, которые соответствуют любому из предпочтений пользователя. Конечно, вы можете легко включить типы мультимедиа в один и тот же запрос.

...