SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 07.07.2008 16:37:32

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Соединение таблиц по условию ON a.id != b.id

Здравствуйте. Есть две таблицы:
a: id int, Name: varchar(50)
b: id int, Title : varchar(50), id_a : int

b ссылается на a через ключ id_a. Мне нужно получить все записи из таблицы a, на которые нет ссылок из таблицы b. Делаю запрос

Код:

SELECT a.Name FROM a JOIN b ON a.id != b.id_a

Если в таблице b есть хоть одна запись, то запрос работает "на ура". Но вот если таблица b пустая, то вместо всех записей из a возвращается пустота. Делать через

Код:

SELECT a.Name FROM a WHERE a.id NOT IN (SELECT DISTINCT b.id_a FROM b)

ибо быстродействие этого запроса оставляет желать лучшего.
Посоветуйте, как быть, пожалуйста! smile

Неактивен

 

#2 07.07.2008 17:37:03

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Соединение таблиц по условию ON a.id != b.id

Вам нужен LEFT JOIN
примерно так:


Код:

SELECT a.Name FROM a LEFT JOIN b ON a.id = b.id_a WHERE b.id_a IS NULL

вроде так, гуру поправят, если ошибся

Отредактированно Shopen (07.07.2008 17:37:52)

Неактивен

 

#3 07.07.2008 17:47:26

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Соединение таблиц по условию ON a.id != b.id

Спасибо, Shopen, пожоже, что это то, что нужно, сейчас попробую.

Неактивен

 

#4 09.07.2008 16:05:36

Student20
Участник
Зарегистрирован: 08.07.2008
Сообщений: 17

Re: Соединение таблиц по условию ON a.id != b.id

Подскажите пожалуйста, а как из а выбрать все записи кроме тех, которые имеют ссылки на них в b с определенным флагом.

Неактивен

 

#5 09.07.2008 16:09:43

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Соединение таблиц по условию ON a.id != b.id

В WHERE добавляешь нужное условие

Неактивен

 

#6 09.07.2008 16:15:03

Student20
Участник
Зарегистрирован: 08.07.2008
Сообщений: 17

Re: Соединение таблиц по условию ON a.id != b.id

а можно пример ? потому и спрашиваю что не получается это условие сделать. те же таблицы только в b есть еще поле флаг

Неактивен

 

#7 09.07.2008 16:20:45

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Соединение таблиц по условию ON a.id != b.id

Задача у тебя поставлена не четко.

Код:

SELECT a.Name FROM a LEFT JOIN b ON a.id = b.id_a WHERE b.id_a IS NULL AND b.Flag = true

или

Код:

SELECT a.Name FROM a LEFT JOIN b ON a.id = b.id_a WHERE b.id_a IS NULL OR b.Flag = true

Неактивен

 

#8 09.07.2008 16:28:22

Student20
Участник
Зарегистрирован: 08.07.2008
Сообщений: 17

Re: Соединение таблиц по условию ON a.id != b.id

Это не совсем то. Так в результате будут все записи на которых нет ссылки в b и записи на которые есть ссылка но с определенным флагом.
А в перовом вашем примере с AND по моему будет всегда результатом 0 строк.

А мне нужно получить все записи из таблицы А кроме тех на которые есть ссылки из B с определенным флагом.
У меня таблица А с вопросами для игры. В таблице B вопрос который задается. но так как два игрока а вопросы они задают друг другу одни и те же (10 вопросов по очереди друг другу) то в таблице В есть флаг , кому сейчас отвечать. Я хочу выбрать из таблицы А все вопросы кроме тех которые задавались игроку.

Неактивен

 

#9 09.07.2008 16:38:38

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Соединение таблиц по условию ON a.id != b.id

А мне нужно получить все записи из таблицы А кроме тех на которые есть ссылки из B с определенным флагом.

Ага, тогда добавь условие в ON:

Код:

SELECT a.Name FROM a LEFT JOIN b ON (a.id = b.id_a AND b.Flag = true) WHERE b.id_a IS NULL

В этом случае у тебя будут все записи из А, а для тех записей из А, которым нашлось соответствие в Б (по id и флагу), поле b.id не будет пустым. Его мы в WHERE и уберем.

Неактивен

 

#10 09.07.2008 16:56:59

Student20
Участник
Зарегистрирован: 08.07.2008
Сообщений: 17

Re: Соединение таблиц по условию ON a.id != b.id

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

Неактивен

 

#11 09.07.2008 17:01:10

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Соединение таблиц по условию ON a.id != b.id

Знал бы ты, как я досадовал на себя, что не додумался до того простого решения, которое подсказал мне Shopen wink

Неактивен

 

#12 09.07.2008 17:32:04

Student20
Участник
Зарегистрирован: 08.07.2008
Сообщений: 17

Re: Соединение таблиц по условию ON a.id != b.id

Интересный момент нашел в мануале.

Manual написал:

6.4.1.1 Синтаксис оператора JOIN
Никогда не следует указывать в части ON какие бы то ни было условия, накладывающие ограничения на строки в наборе результатов. Если необходимо указать, какие строки должны присутствовать в результате, следует сделать это в выражении WHERE.

5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN
Все условия LEFT JOIN перемещаются в предложение WHERE.

AND b.Flag = true - это же получается условие ограничения на строки ? но ведь если его вынести в where получается совсем не то что нужно =\

Неактивен

 

#13 09.07.2008 18:14:48

Student20
Участник
Зарегистрирован: 08.07.2008
Сообщений: 17

Re: Соединение таблиц по условию ON a.id != b.id

Код:

 SELECT a.Name FROM a LEFT JOIN b ON (a.id = b.id_a AND b.Flag = true) WHERE b.id_a IS NULL

AND b.Flag = true это я и к тому что как вместо true подставить теперь поле из другой таблицы. Чтобы было чтото вроде :

Код:

 SELECT a.Name FROM c, a LEFT JOIN b ON (a.id = b.id_a AND b.Flag = c.flag) WHERE b.id_a IS NULL

Неактивен

 

#14 09.07.2008 18:37:47

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Соединение таблиц по условию ON a.id != b.id

Если я правильно Вас понял, то Вам нужно объединить несколько табличек таким образом.
Можете писать просто так, как думается:

SELECT ... FROM a LEFT JOIN b ON (связь a <-> b) LEFT JOIN c ON (связь того, что слева, с c) ... WHERE (условия ограничения)

Т.е. в Вашем случае как-то так:
SELECT a.Name FROM a LEFT JOIN b ON (a.id = b.id_a) LEFT JOIN c ON (b.Flag = c.flag) WHERE b.id_a IS NULL

Неактивен

 

#15 09.07.2008 18:47:47

Student20
Участник
Зарегистрирован: 08.07.2008
Сообщений: 17

Re: Соединение таблиц по условию ON a.id != b.id

То что вы написали понял, спасибо. )

А нельзя вынести b.Flag = true как то из JOIN в WHERE ? У меня просто таблиц больше чем три, их все надо связать чтобы получить флаг для b.Flag. В where это было бы проще. У меня такая связь между таблицами:
games.game_id=1 AND players.game_id=games.game_id AND players.player_id=5 AND players.id_gp=player_tasks.id_gp

b.Flag=player_tasks.id_gp чтобы так получить нужно все таблицы объеденить через JOIN ?

P.S. я бы с удовольствием вас не мучал, но кроме мануала по JOIN ничего доступного найти не смог.

Отредактированно Student20 (09.07.2008 18:51:45)

Неактивен

 

#16 09.07.2008 19:15:44

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Соединение таблиц по условию ON a.id != b.id

Запись
SELECT ... FROM a, b WHERE (a<->b)
эквивалентна полностью записи
SELECT ... FROM a JOIN b on (a<->b) (но join внутренний, а не левый).

Так что в принципе никто не мешает Вам выбирать данные по такой схеме:
SELECT ... FROM a, b, c, d, e LEFT JOIN f ON (e<->f) WHERE cond(a) AND cond(b) ... AND f.field IS NULL

Единственное сложное тут - сообразить, с чем реально связана таблица f по
внешней связи так, чтобы правильно отработала выборка значений NULL.

P.S. Внутренняя связь отличается от внешней тем, что никогда не выбирает строки, если хотя бы
в одной таблице отношений нет значений, т.е. не выбирает NULLы.

Неактивен

 

#17 09.07.2008 20:03:42

Student20
Участник
Зарегистрирован: 08.07.2008
Сообщений: 17

Re: Соединение таблиц по условию ON a.id != b.id

А что такое cond (a)?

SELECT a.Name FROM a LEFT JOIN b ON (a.id = b.id_a),c WHERE  b.id_a IS NULL AND b.flag=c.flag;
и
SELECT a.Name FROM a LEFT JOIN b ON (a.id = b.id_a) LEFT JOIN c ON (b.Flag = c.flag) WHERE b.id_a IS NULL;

Это эквивалентные запросы ? )

Неактивен

 

#18 09.07.2008 21:54:49

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Соединение таблиц по условию ON a.id != b.id

Это просто некоторое условие на a smile

Запросы не эквивалентные, т.к. второй допускает строчки с c.flag = NULL.

Если c.flag не бывает NULL, то эквивалентные.

Неактивен

 

#19 10.07.2008 09:41:31

Student20
Участник
Зарегистрирован: 08.07.2008
Сообщений: 17

Re: Соединение таблиц по условию ON a.id != b.id

Спасибо paulus, Magz. smile разобрался и благодарен за помощь. )

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson