Запрос из 3х таблиц

kramcd
Дата: 17.01.2012 13:53:28
Есть 3 таблицы:
1-Клиенты с полями id(счетчик) и ФИО(текст)
2-Филиалы с полями id(счетчик) и Адрес(текст)
3-Заказы с полями id(счетчик), Клиент(Подстановка) и Филиал(подстановка)

Запрос звучит так:
Получите список клиентов, которые обращались во все филиалы фирмы.

Сперва сделал так:
SELECT ФИО
FROM Клиенты INNER JOIN Заказы
ON Клиенты.id=Заказы.Клиент
GROUP BY ФИО
HAVING Count(Заказы.Филиал)=(SELECT Count(id) FROM Филиалы);


Но потом понял что в одном филиале, клиент может сделать заказов больше чем 1. Попытался убрать из выборки повторяющиеся по полю Филиал записи, так:
SELECT DISTINCT Филиал, ФИО
FROM Клиенты INNER JOIN Заказы
ON Клиенты.id=Заказы.Клиент
GROUP BY ФИО
HAVING Count(Заказы.Филиал)=(SELECT Count(id) FROM Филиалы); 

Но получил ошибку: Попытка выполнить запрос, который не включает указанное выражение "Филиал" как часть агрегатной функции.

Нужно либо каким-то другим способом убрать повторяющиеся по полю Филиал записи, либо найти другой способ решения. Есть предложения?
Rivkin Dmitry
Дата: 17.01.2012 14:21:22
Идея такая: сначала найти всех клиентов, которые НЕ были хотя бы в одном из филиалов:
	select z.[Клиент]
	from [Филиал] f
	left join [Заказы] z
	on f.id = z.[Филиал]
	where z.[Клиент] is null

А затем уже выделить из списка клиентов оставшихся - они побывали во всех филиалах


select [ФИО]
from [Клиент]
where id not in (
	select z.[Клиент]
	from [Филиал] f
	left join [Заказы] z
	on f.id = z.[Филиал]
	where z.[Клиент] is null)


Код в терминах SQL Server, го я думаю, важнее тдея, а перевести в Акс не составит труда
energy75
Дата: 17.01.2012 14:30:20
Код дмитрия изящен, и лучшего того, что наваял я. Однако на БОЛЬШИХ таблицах in select выполняется медленно.

мое:
SELECT tb1.fio
FROM (SELECT distinct  clients.fio, zakazy.filial
FROM clients RIGHT JOIN zakazy ON clients.id = zakazy.client) AS tb1
GROUP BY tb1.fio
HAVING (((Count(tb1.filial))=(SELECT Count(filials.id) AS [Count-id]
FROM filials)));
energy75
Дата: 17.01.2012 14:31:32
Дмитрия конечно же! (sorry)
Rivkin Dmitry
Дата: 17.01.2012 14:34:38
energy75
Дмитрия конечно же! (sorry)

Порадовал! В иврите все буквы то ли заглавные, то ли строчные. Да к тому же "Вы" - только множественное число!
Rivkin Dmitry
Дата: 17.01.2012 14:37:42
energy75
Код дмитрия изящен, и лучшего того, что наваял я. Однако на БОЛЬШИХ таблицах in select выполняется медленно.
[/src]


Совсем не обязательно, зависит от правильности создания индексов. И к тому же, всегда можно заменить на join
energy75
Дата: 17.01.2012 14:42:47
Rivkin Dmitry
energy75
Дмитрия конечно же! (sorry)

Порадовал! В иврите все буквы то ли заглавные, то ли строчные. Да к тому же "Вы" - только множественное число!


Ничего не понял... Лесенка навеяла??
energy75
Дата: 17.01.2012 14:44:15
Вот оно че.... сосед Саныча оказывается!
kramcd
Дата: 17.01.2012 14:58:41
Rivkin Dmitry и energy75, спасибо большое !

Сделал по способу energy75, т.к способ Rivkin Dmitry не сработал, по каким-то причинам при Left Join у меня терялась строка с пустым полем Клиент, то есть результат был как при использовании INNER JOIN и подзапрос выдавал всегда пустую таблицу .
Rivkin Dmitry
Дата: 18.01.2012 13:48:18
Появилось немного времени, решил проверить и доработать.
Идея та же - сначала найти всех клиентов, которые не бывали хотя бы в одном из филифлов.
Значит, надо создать таблицу (запрос) со всеми возможными пересечениями клиентов и филиалов:
Я его назвал (BC)

SELECT Brunch.id_brunch, Client.id_client
FROM Brunch, Client;


А тепрь сравнить его с таблицей заказов:

SELECT Client.Name
FROM Client
WHERE (((Client.id_client) Not In (SELECT t.id_client
FROM BC AS t LEFT JOIN [Order] ON (t.id_client = Order.id_client) AND (t.id_brunch = Order.id_brunch)
WHERE (((Order.id_order) Is Null)))));