Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Составление SQL-запросов > Прверить наличие определенной записи в таблице


Автор: Чoо 15.7.2010, 23:33
Вообще возможно составить такой запрос?, если да, то как он будет выглядеть?

Что-то копал в сторону использования Exists и создания вычисляемого столбца, хранящего в записи истину или ложь, но так ни к чему и не пришел.

вариант 
Код

Select NAME from EMPLOYEE where NAME = 'Vasya'

не устраивает, так как Васей в таблице может быть много

вот если бы можно было бы предыдущее выражение поместить в Exists, а результат ИСТИНА или ЛОЖЬ вернуть клиенту..  smile  

вариант 
Код

Select count(NAME) from EMPLOYEE where NAME = 'Vasya'

так же не устраивает, так как вась можеть быть очень много

Автор: Данкинг 15.7.2010, 23:54
Цитата(Чoо @  16.7.2010,  00:33 Найти цитируемый пост)
не устраивает, так как Васей в таблице может быть много

А какой Вася нужен-то? smile 

Автор: Чoо 16.7.2010, 00:03
ну вообще вася приведен в качестве примера, а сама задача нетривиальная:

Есть таблица TBL1, хранящая названия групп и их ID (ID - первичный ключ)

Есть другая таблица TBL2, хранящая наименование объекта и в качестве его характеристик прочие поля + внешний ключ, ссылающийся на ID группы, таблицы TBL1). Объектов, ссылающихся на один и тот же ID может быть очень много.

И теперь есть программа-клиент, которой при заполнении  списка групп надо подсветить те группы, на которые есть ссылки в таблице TBL2. 

вобщем нужно произвести действие, аналогичное компоненту доступа к данным Table.Locate(<поле>, прочие параметры), только курсор не нужно устанавливать.

может так сделать?
Код

Select distinct NAME from EMPLOYEE where NAME = 'Vasya'

или все-таки есть способ получить результат проверки exists(), что было бы предпочтительней?

Автор: chip_and_dayl 16.7.2010, 01:00
А если сделать левое внешнее объединение.  Поля или поле со второй таблицы скрыть. И проверять, если нил, то нету ссылки, если не нил, то есть ссылка

Добавлено через 3 минуты и 30 секунд
То беж результатом должно быть

поля с Таблицы 1              поля с  Таблицы 2
ИД  Название_группы      ИД_ссылающий_на_таблицу_1

Поле ИД_ссылающий_на_таблицу_1 в программе скрываем, оно служит в качестве вычисляемого поля, где нил или значение

Автор: skyboy 16.7.2010, 01:41
два запроса. первый - выбор списка групп.
второй - select distinct(id_group) from tbl2
недостаток - разделение данных, относящихся к одному объекту.
достоинство - если есть дополнительная фильтрация в списке групп и/или разбивка по количеству(страничность), то во втором вопросе вернутся только "признаки" для выбранных групп.
вариант с внешним объединением лично мне не по душе тем, что либо группировку придется использовать, либо же получится потенциально довольно внушительный результат соединения таблиц.

Автор: Чoо 16.7.2010, 01:42
chip_and_dayl,  тоесть сделать так?:
Код

Select ID from TBL1 left outer join TBL2 on  TBL1.ID= TBL2.TBL1_ID

но ведь в этом случае я от сервера получу весь столбец ID, только строки, не соответствующие первичному ключу первой таблицы будут заполнены NULL

Автор: skyboy 16.7.2010, 01:45
если групп немного, то можно попробовать разбить запрос на два:
Код

(select distinct(tbl1.id), "1"
from tbl1
inner join tbl2
on tbl2.id_group = tbl1.id)
union all
select tbl1.id, "0"
from tbl1
left join tbl2
on tbl2.id_group = tbl1.id
where tbl2.id_group is null

все же внешнее соединени, да smile
правда, при наличии индекса на tbl2.id_group должно шустро работать.

Добавлено @ 01:49
хотя, можно и запрос с existsin проверить. наверное, скорость будет не ниже.
Код

select tbl1.id, "1"
from tbl1
where tbl1.id in (select id_group from tbl2)
union all
select tbl1.id, "0"
from tbl1
where tbl1.id not in (select id_group from tbl2)

тут было ошибочное использование конструкции exists по форме конструкции in. перепутал, извините.

Автор: Чoо 16.7.2010, 01:49
Цитата(skyboy @  16.7.2010,  01:41 Найти цитируемый пост)
два запроса. первый - выбор списка групп.второй - select distinct(id_group) from tbl2

Код

Select GROUPNAME from TBL1 where exists(select TBL1_ID from TBL2 join TBL1 on TBL2.TBL1_ID=TBL1.ID)

так?smile
пока писал вы уже ответили. Читаю

Добавлено через 9 минут и 46 секунд
skyboy, а что означают цифры 1 и 0?  smile  (SQL не так давно изучаю, поэтому долго думаю какой результат запроса получу)

Автор: skyboy 16.7.2010, 02:24
Цитата(Чoо @  16.7.2010,  00:49 Найти цитируемый пост)
skyboy, а что означают цифры 1 и 0? 

ну, поле-признак в результате запроса. "0" - значит отсутствует в связанной таблице, "1" - присутствует.
Цитата(Чoо @  16.7.2010,  00:49 Найти цитируемый пост)
так?

да, наверное.
вот только что понял, что я неправильно использовал конструкцию exists.
в моем варианте вместо "exists in" надо оставить просто "in"
грубая синтаксическая ошибка, обидно :(

Автор: Чoо 16.7.2010, 02:43
skyboy, синтаксическую ошибку я исправил сразу, но вот на поле-признак сервер ругаетcя. (firebird 2.1)

Добавлено через 13 минут и 14 секунд
без единицы и нуля получаю список ID первой таблицы.
Без объединения (только первый запрос) получаю ID, на которые есть внешние ключи во второй таблице (разумеется без дубликатов). Ну и только второй запрос - ID, на которые нет внешних ключей.

Автор: Чoо 16.7.2010, 03:10
Цитата(Чoо @  16.7.2010,  01:49 Найти цитируемый пост)
Код

Select GROUPNAME from TBL1 where exists(select TBL1_ID from TBL2 join TBL1 on TBL2.TBL1_ID=TBL1.ID)

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

надо было так:
Код

Select G.GROUPNAME from TBL1 as G where exists(select D.TBL1_ID from TBL2 as D where G.ID=D.TBL1_ID)


но все-равно это не то.. Или сервер от этого сильно не напрягается? smile

Автор: Чoо 16.7.2010, 03:26
skyboy, в принципе вариант похож на ваш, только мне придется делать два запроса: получать сначала группЫ, на которые есть внешние ключи, а затем группы, на которые нет внешних ключей. 
Если учесть, что список групп всегда загружается полностью (он тож группируется, так что даже если групп будет около сотни, они в разных категориях и пользователь без труда сможет с ними разобраться), а так же, что exists вернет истину как только найдет нужное значение, то в принципе лишних действий не производится, лишний тарфик не генерируется и вобщем все норм.
Но существует ли более изящный способ?

***
извиняюсь за сообщения подряд - все не привыкну, что они не склеиваются.

Автор: Zloxa 16.7.2010, 08:57
Цитата(Чoо @  16.7.2010,  00:03 Найти цитируемый пост)
при заполнении  списка групп надо подсветить те группы, на которые есть ссылки в таблице TBL2. 

Код

select tbl1.* 
   , case when exists (select null from tbl2 wehre tbl2.tbl1_id = tbl1.id)
      then 'Y'
      else 'N'
     end must_be_highlighted
from TBL1

Автор: Чoо 16.7.2010, 12:59
Zloxa, ух ты, то что нужно  smile 

Всем спасибо за помощь, вопрос решен smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)