Запрос: отобрать свободные...

Работа VB и СУБД (Access, MSSQL, MySQL, Oracle и пр.)
Правила форума
При создании новой темы не забывайте указывать используемую СУБД.
Leon_
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 333
Зарегистрирован: 19.05.2004 (Ср) 16:31
Откуда: Moscow

Запрос: отобрать свободные...

Сообщение Leon_ » 05.07.2004 (Пн) 9:16

Вроде бы простой SQL-запрос, но я что-то потерялся в трех соснах.. :roll:
Есть таблицы tblTask (c полями [Task_ID], [Employee_ID], [Field],...),
tblEmployee(поля [Employee_ID], [LastName],...). Связаны отношением "один-к-одному" по [Employee_ID], т.е. одной задаче назначается один сотрудник, и только один раз.
Как отобрать те записи сотрудников из tblEmployee, которые еще свободны (не назначены)?

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 05.07.2004 (Пн) 10:13

select *
from tblEployee
where Employee_ID is null
Lasciate ogni speranza, voi ch'entrate.

Leon_
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 333
Зарегистрирован: 19.05.2004 (Ср) 16:31
Откуда: Moscow

Сообщение Leon_ » 05.07.2004 (Пн) 10:30

В моем варианте это не подойдет: [Employee_ID] в tblEmployee -- ключевое поле (AutoNumber типа).

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 05.07.2004 (Пн) 10:39

Э... Тогда дизайн неправильный :)
Такая структура больше соответствует "один-ко-многим". Ну тогда так (не уверен, что Access поддерживает данную конструкцию):
Код: Выделить всё
select *
from tblEmployee
where Employee_ID not in
  (
    select Employee_ID
    from tblTask
  )



[EDIT] Или такой варинт:
Код: Выделить всё
select Employee_ID
from tblEmployee

minus

select tblEmployee.Employee_ID
from tblEmployee, tblTask
where tblEmployee.Employee_ID = tblTask.Employee_ID
Lasciate ogni speranza, voi ch'entrate.

Leon_
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 333
Зарегистрирован: 19.05.2004 (Ср) 16:31
Откуда: Moscow

Сообщение Leon_ » 05.07.2004 (Пн) 11:37

:D Уважаю! То, что нужно (1 вариант, правда работает очень медленно :? ).
Готов принять критику дизайна схемы данных :lol:
??
tblTask и tblEmployee -- две таблицы для независимых сущностей (добавляются разными пользователями в разное время с разными целями). В каждой примерно по 1500 записей. Обе модержат ключевые поля. Я прежде использовал флаг [Occupied] (Bool) в tblEmployee для признака "назначен/неназначен", потом надоело. Так как же правильней :?:

Sedge
Alternative Choice
Alternative Choice
Аватара пользователя
 
Сообщения: 1049
Зарегистрирован: 16.05.2002 (Чт) 18:23
Откуда: Somewhere-In-The-Net

Сообщение Sedge » 05.07.2004 (Пн) 11:37

Или так (код для SQL-Server):

Код: Выделить всё
SELECT
    tblEmployee.[Employee_ID] AS [id_1],
    tblTask.[Employee_ID] AS [id_2]
FROM
    tblEmployee LEFT OUTER JOIN tblTasks ON
       tblEmployee.[Employee_ID] = tblTask.[Employee_ID]
WHERE
    ISNULL(tblTask.[Employee_ID], -1) = -1

Leon_
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 333
Зарегистрирован: 19.05.2004 (Ср) 16:31
Откуда: Moscow

Сообщение Leon_ » 05.07.2004 (Пн) 11:42

2Sedge:
Спасибо за помощь. Я позабыл указать что у меня Access 2002 с базой MDB.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 05.07.2004 (Пн) 11:50

Кстати, да.
Соеденяешь через LEFT OUTER JOIN и отбираешь только те, у которых tblTask.Employee_ID Is Null.
Lasciate ogni speranza, voi ch'entrate.

Sedge
Alternative Choice
Alternative Choice
Аватара пользователя
 
Сообщения: 1049
Зарегистрирован: 16.05.2002 (Чт) 18:23
Откуда: Somewhere-In-The-Net

Сообщение Sedge » 05.07.2004 (Пн) 12:18

Leon_ писал(а):2Sedge:
Спасибо за помощь. Я позабыл указать что у меня Access 2002 с базой MDB.


Тогда пишешь так, как alibek подсказал:

Код: Выделить всё
SELECT
    tblEmployee.[Employee_ID] AS [id_1],
    tblTask.[Employee_ID] AS [id_2]
FROM
    tblEmployee LEFT OUTER JOIN tblTasks ON
       tblEmployee.[Employee_ID] = tblTask.[Employee_ID]
WHERE
    tblTask.[Employee_ID] Is Null 

Leon_
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 333
Зарегистрирован: 19.05.2004 (Ср) 16:31
Откуда: Moscow

Сообщение Leon_ » 05.07.2004 (Пн) 13:13

:D Да, так тоже хорошо. Спасибо. Как бы только выяснить, какой из вариантов быстрее, но это уже Optional.
PS: В конструкторе запросов Access (база MDB) конструкция OUTER не поддерживается. Поэтому я передал этот запрос рекордсету ADO, и вот там уже OK. Это все из-за различий в стандартах SQL?

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 06.07.2004 (Вт) 12:47

SELECT * FROM tblEmployee
WHERE NOT EXISTS(SELECT * FROM tblTask
WHERE Employee_ID=tblEmployee.Employee_ID)
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 06.07.2004 (Вт) 12:51

Вообще-то при правильном написании запроса и правильных индексах ответ должен быть получен практически мгновенно...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Leon_
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 333
Зарегистрирован: 19.05.2004 (Ср) 16:31
Откуда: Moscow

Сообщение Leon_ » 06.07.2004 (Вт) 13:34

Да, такой запрос
Andrey Fedorov писал(а):SELECT * FROM tblEmployee
WHERE NOT EXISTS(SELECT * FROM tblTask
WHERE Employee_ID=tblEmployee.Employee_ID)

работает в моем случае быстрее, чем
Код: Выделить всё
select *
from tblEmployee
where Employee_ID not in
  (
    select Employee_ID
    from tblTask
  )

В среднем, быстрее в 2,5 раза (измерял с секундомером в руке на последовательности запусков :wink: ). Спасибо и за этот пример.


Вернуться в Базы данных

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот и гости: 6

    TopList