Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Как составить запрос без использования IN и EXISTS?  [new]
Naile
Member

Откуда: Latvija
Сообщений: 145
Помогите, пожалуйста составить запрос
Есть три таблицы.
Таблица Account - данные об абонентах, Document - информация об абонируемом издании, с датами абонирования
(в таблице Account почти 85000 записей, в таблице Document почти полмиллиона, и данные будут увеличиваться).
Product - каталог с изданиями, примерно около 20 записей.

Account
Id, Name, Address
Document
Id, AccountId, DateFrom, DateTo, ProductId
Product
Id, Name

Необходимо найти персон, которые абонировали список конкретных ProductId, например, с 01.01.2013 по любую дату 2013 года, но не сделали абонирования с 01.01.2014
При этом необходимо, чтобы сравнение шло не по AccountId, а по адресу. Т.к. возможны варианты, что в 2013 году заказ на себя делал один член семьи, а в 2014 - другой. Тогда AccountId разный, но адрес одинаковый.

Я создала необходимый запрос, но использовала IN, EXISTS и NOT EXISTS
В результате, в SQL я жду данные до 10 минут (при том, что примерное возвращаемое число, в среднем, 2000 записей).
А с учетом того, что данные я запрашиваю и возвращаю в C# проект, я их там вообще не могу дождаться...

Насколько я понимаю, все эти вещи (IN, EXISTS и NOT EXISTS) - очень увеличивают время запроса.
И как я понимаю, их можно переделать на JOIN... WHERE <что-то> = null, но не очень понимаю как это можно сделать.
Буду признательна за помощь.


Если надо - выложу запрос, которы мною уже написан.
12 янв 14, 02:19    [15403756]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
leov
Member

Откуда: С-Петербург
Сообщений: 616
Naile,

без запроса то вроде и говорить не о чем
12 янв 14, 02:27    [15403764]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Naile
Member

Откуда: Latvija
Сообщений: 145
select distinct 

LTRIM(RTRIM(a.Name)) as Persona, 
Address as Adrese, 
Phone as Telefons_1, 
AdditionalPhone as Telefons_2, 
Email as Epasts 

from Account a
inner join Document doc ON doc.AccountId = a.Id

where a.Id in 

(select acc.Id from Account acc 
inner join Document doc ON doc.AccountId = acc.Id
where
	
	EXISTS(select * from Document docExists
			inner join Account accExists ON accExists.Id = docExists.AccountId
				where StartDate = '2013-01-01' and DueDate <= '2013-12-31' and 				
				accExists.Address = acc.Address
			)
	and
	NOT EXISTS(select * from Document docNotExists 
			inner join Account accNotExists ON accNotExists.Id = docNotExists.AccountId
			where StartDate >= '2014-01-01' and 	
			accNotExists.Address = acc.Address	
		)

	and doc.ProductId in (<Продукт1>, <Продукт2>, <Продукт3>, <Продукт4>)
)

and doc.ProductId in (<Продукт1>, <Продукт2>, <Продукт3>, <Продукт4>)

	 and doc.StartDate = '2013-01-01' and doc.DueDate <= '2013-12-31'


order by LTRIM(RTRIM(a.Name)) 
12 янв 14, 02:33    [15403773]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
sdet
Member

Откуда:
Сообщений: 463
Naile,
Не стоит расстраиваться. Надо посмотреть в план выполнения запроса
12 янв 14, 02:59    [15403810]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
sdet
Member

Откуда:
Сообщений: 463
sdet,
Но в любом случае запрос надо переписывать из-за повторений и избыточности конструкций
12 янв 14, 03:14    [15403819]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
leov
Member

Откуда: С-Петербург
Сообщений: 616
Naile,

как-то больно сложно вы выражаете мысли. не до конца понимаю что тут написано

правильно ли сказать что вот это перечень экаунтов которые заказывали в прошлом году один из продуктов списка?
Naile
которые абонировали список конкретных ProductId, например, с 01.01.2013 по любую дату 2013 года
select distinct AccountID
from Document
where ProductId in (<Продукт1>, <Продукт2>, <Продукт3>, <Продукт4>)
  and StartDate = '2013-01-01'
  and DueDate <= '2013-12-31'

а вот это перечень экаунтов которые заказывали один из этих продуктов в 14 году?
Naile
не сделали абонирования с 01.01.2014
select distinct AccountID
from Document
where ProductId in (<Продукт1>, <Продукт2>, <Продукт3>, <Продукт4>)
  and StartDate > '2014-01-01'
12 янв 14, 03:18    [15403823]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Naile
Member

Откуда: Latvija
Сообщений: 145
Прошу прощения за невнятную постановку задачи.
Суть в том, что Вася в 2013 году выписал себе газету "Правда", а в 2014 году - не выписал. И он должен попасть в список!
Но! Если вдруг Васин жена заказала на 2014 год газету "Правда", и у нее такой же адрес как у Васи, то Васи в списке не должно быть.

leov
да, Вы правильно все расписали...
12 янв 14, 14:31    [15404515]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
invm
Member

Откуда: Москва
Сообщений: 9400
Naile
Суть в том, что Вася в 2013 году выписал себе газету "Правда", а в 2014 году - не выписал. И он должен попасть в список!
Но! Если вдруг Васин жена заказала на 2014 год газету "Правда", и у нее такой же адрес как у Васи, то Васи в списке не должно быть.
Только вот у Васи адрес значится как "ул. Главная, д. 1", а у его жены как "улица Главная, д. 1" или "Главная ул., д. 1"
12 янв 14, 15:27    [15404595]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Naile
SELECT	DISTINCT
	LTrim(RTrim(A.Name))	AS Persona	-- Не допускать мусора
,	A.Address		AS Adrese
,	A.Phone			AS Telefons_
,	A.AdditionalPhone	AS Telefons_2
,	A.Email			AS Epasts
FROM	dbo.Account	A
JOIN	dbo.Document	D ON D.AccountID = A.ID	-- Зачем это тут?
WHERE	D.ProductID	IN (<Продукт1>,<Продукт2>,<Продукт3>,<Продукт4>)
AND	D.StartDate	 = '2013-01-01'		-- Очепятка
AND	D.DueDate	<= '2013-12-31'
AND	A.ID IN (	-- А смысл связки само на себя?
	SELECT	AСС.ID
	FROM	dbo.Account	ACC
	JOIN	dbo.Document	D ON D.AccountID = ACC.ID
	WHERE	D.ProductID	IN (<Продукт1>,<Продукт2>,<Продукт3>,<Продукт4>)
	AND	Exists(	SELECT	*
			FROM	dbo.Account	AE
			JOIN	dbo.Document	DE ON DE.AccountID = AE.ID
			WHERE	AE.Address	 = ACC.Address
			AND	DE.StartDate	 = '2013-01-01'		-- Очепятка
			AND	DE.DueDate	<= '2013-12-31')	-- Неправильный подход
	AND NOT	Exists(	SELECT	*
			FROM	dbo.Account	ANE
			JOIN	dbo.Document	DNE ON DNE.AccountID = ANE.ID
			WHERE	ANE.Address	 = ACC.Address
			AND	DNE.StartDate	>= '2014-01-01')
	)
ORDER BY LTrim(RTrim(A.Name))	-- ORDER BY 1
По порядку:
1. Всегда пишите схему у объектов базы (таблицы и т.п) [иначе компиляция будет откладываться]
2. Всегда пишите алиасы. [вы и мы не запутаемся и предотвращает ошибки и скулю проще]
3. Trim - не допускайте мусора в базе. Нужно было чистить на момент вставки. Вставка делается раз, а запросы 100500 - при которых делается очень не дешёвая операция Trim.
Нужно исправить вставку, почистить данные, наложить констрайнт на поле и убрать этот трим из всех запросов.
4. StartDate = '2013-01-01' Очепятка
5. DueDate <= '2013-12-31' Так лучше никогда не пишите. Время пространственная величина, она непрерывна. Поэтому всегда пишите по принципу: " >= AND < ". Т.е. с одной стороны с равенством, а с другой строгое неравенство.
Ту даже темка (BETWEEN) есть злободневная, и мне пока не каждому удаётся объяснить ошибку мышления у гуманитариев.
6. Зачем вам таблица dbo.Document в самом внешнем запросе? Это излишество которое просто убивает большую часть времени. Все необходимые условия же есть внутри.
7. Зачем вообще первый IN и внешний запрос. Первый внутренний запрос уже обладает нужными строками.
8. В ваших EXISTS-ах вообще нет указания продуктов, в итоге вы ищете абонирования не по конкретным продуктам, а были какие либо абонирования вообще. Т.е. заказал газету "правда", при котором есть заказы по "мурзилка" и нет ни одного заказа на что либо вообще.
9. Первый EXISTS (3я вложенность) бессмыслен, вы уже во внешнем запросе отобрали нужное.
10. Ваш DISTINCT образовался из-за того что перемножается на dbo.Documents, и также ест ресурсы.
11. Непонятно: почему две колонки StartDate и DueDate ?

Бардак у вас голове. Вам этим не нравится заниматься и в этом проблема. А там ничего сложного. Повысить интерес и не привить отвращение поможет sql-ex.ru. От простого к сложному, при этом забавно - ибо будете больше думать о предметах самой задачи. Фан должен быть при обучении.

Названия таблиц - бальзам на душу. Грамотно - никакого множественного числа, словно человек понимает философию реляционных БД.

Предварительный запрос, для понимания как должна описываться задача:
SELECT	LTrim(RTrim(A.Name))	AS Persona	-- TODO: Избавится от мусора в базе
,	A.Address		AS Adrese
,	A.Phone			AS Telefons_
,	A.AdditionalPhone	AS Telefons_2
,	A.Email			AS Epasts
FROM	dbo.Account	A
WHERE	Exists(	SELECT	*
		FROM	dbo.Document	D
		WHERE	D.AccountID	 = A.ID	-- Связка
		AND	D.ProductID	IN (<Продукт1>,<Продукт2>,<Продукт3>,<Продукт4>)
		AND	D.StartDate	>= '2013-01-01'
		AND	D.DueDate	<  '2014-01-01'	-- Так проще, точнее и надёжнее
		AND NOT	Exists(	SELECT	*
				FROM	dbo.Account	ANE
				JOIN	dbo.Document	DNE ON DNE.AccountID = ANE.ID
				WHERE	ANE.Address	 = A.Address	-- Связка
				AND	DNE.ProductID	 = D.ProductID	-- Связка
				AND	DNE.StartDate	>= '2014-01-01')
			)
ORDER BY 1
Далее надо смотреть планы. Их всегда надо смотреть. И убедится что всё идёт правильно. Что хватает нужных индексов и скуль понял задачу. Бывает порой он понимает лучше как надо сделать чем разработчик.

Я стараюсь писать так чтобы запрос заодно отражал как оно будет отбираться (в основном это очевидно и зависит только от задачи). Но в данном случае первым должен отбираться dbo.Document (индекс на продукт, дате), далее связка по dbo.Account (PK), далее поиск dbo.Account по адресу (должен быть индекс на это поле), далее опять dbo.Document по клиенту, продукту, дате (должен быть соответствующий индекс).
С индексами осторожнее, слишком много плохо - тормозит вставка, и поэтому есть альтернативный вариант запроса, который тормознее, но зато в других местах лучше. Тут надо понимать систему в целом чтобы сделать выбор.

И жду ответа про StartDate и DueDate. Ибо это также влияет на производительность.
12 янв 14, 15:55    [15404639]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Naile
Member

Откуда: Latvija
Сообщений: 145
Mnior
По поводу StartDate - это не опечатка. Необходимо вычислить именно журналы/газеты, которые начали именно с первого января выписывать. В феврале нужно будет делать запрос для 1-го февраля
По поводу DueDate я поняла, т.е. надо "сверху" ее ограничить - DueDate between '2013-01-01' and '2013-12-31'. Так?
12 янв 14, 16:03    [15404653]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
invm
Только вот у Васи адрес значится как "ул. Главная, д. 1", а у его жены как "улица Главная, д. 1" или "Главная ул., д. 1"
Да, и тут проблема которую надо понять как правильно решить.
Для адресов возможно стоит занести отдельную таблу, а далее уже связывать по ID - будет лучше работать.
С одной стороны может показаться что лучше связывать родственников явно (спец таблой), но в данном ракурсе понятно что дело не в родственных связях, а именно в месте проживания, и что адресс есть очень важная часть системы и поэтому должна сильно контролироваться.
Т.е. должно быть не просто отдельная табла, но ещё жёстко регламентирована структура, никаких общих полей, улицы, дома и т.п. отделены. Короче гемор который компания обязана преодолеть.

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

Так что я предпочёл считать поле Address не строковым, а глобальным идентификатором, и на клиенте он автоматически показывает местоположение.
12 янв 14, 16:06    [15404661]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Naile
Member

Откуда: Latvija
Сообщений: 145
Прощу прощения, не до конца прочитала относительно DueDate. Насчет < '2014-01-01' поняла...

"Зачем тут это" - я в самых двух последних строках ограничиваю условием по документам. Иначе (почему-то???) у меня ненужные данные вылезают - возможно это ошибка внутри запроса?

Так или иначе, например, если я это условие не ставлю
and doc.ProductId in (<Продукт1>, <Продукт2>, <Продукт3>, <Продукт4>)

	 and doc.StartDate = '2013-01-01' and doc.DueDate <= '2013-12-31'


order by LTRIM(RTRIM(a.Name)) 

у меня для определенного издания выходит 79 клиентов, в то время как с ним - 17.
И проверив клиентов, которые не попадают в 17, я не вижу у них требуемого издания...
12 янв 14, 16:10    [15404669]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
iap
Member

Откуда: Москва
Сообщений: 47000
Naile
Mnior
По поводу StartDate - это не опечатка. Необходимо вычислить именно журналы/газеты, которые начали именно с первого января выписывать. В феврале нужно будет делать запрос для 1-го февраля
По поводу DueDate я поняла, т.е. надо "сверху" ее ограничить - DueDate between '2013-01-01' and '2013-12-31'. Так?
Mnior же написал Вам
DueDate >= '2013' AND DueDate < '2014'
Правда, я не читал и не понимаю, что это за дата - DueDate...
12 янв 14, 16:13    [15404673]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Naile
Member

Откуда: Latvija
Сообщений: 145
автор
Только вот у Васи адрес значится как "ул. Главная, д. 1", а у его жены как "улица Главная, д. 1" или "Главная ул., д. 1"

с заказчиком это было обговорено, это уже "не мои проблемы". Ищем именно "ул. Главная, д. 1". Если не находим - значит Васю в список.

"улица Главная, д. 1" или "Главная ул., д. 1"
- не считаются равными адресами.
12 янв 14, 16:13    [15404676]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Naile
Member

Откуда: Latvija
Сообщений: 145
По поводу адреса - на самом деле у меня и есть отдельные таблицы для адресов.
Прошу прощения, если я всех сбила с толку, просто я хотела более "короткий" вариант показать. Я решила, что на суть вопроса это не влияет.
Просто в таблице Account есть и после Address, и всевозможноые RegionId, StateId, MuncipalityId, CityId, VillageId, Street, Building, Apartment, Zip.
И сравнения я делаю по ним...
А Address - написала для краткости.

Может если кто знает - я работаю с системой BPMonline (7 версия). И вот внутри системы такой запрос нельзя сделать, потому и возникла необходимость сделать отдельный плагин, который будет в виде Excel возвращать такие данные.
12 янв 14, 16:19    [15404683]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Naile
По поводу DueDate я поняла, т.е. надо "сверху" ее ограничить - DueDate between '2013-01-01' and '2013-12-31'. Так?
1. Да.
2. бл?*:!. Я же писал что не надо использовать ">= AND <=" для времени.
Правильно будет:
    D.DueDate >= '2013-01-01'
AND D.DueDate <  '2014-01-01'

Naile
По поводу StartDate - это не опечатка. Необходимо вычислить именно журналы/газеты, которые начали именно с первого января выписывать.
Колотить её в качаль.
У вас нарушена 2я нормальная форма. Нужна отдельная таблица для этого.

Если считать что могут быть записи где продукт и адрес одинаковы, а StartDate разные (отличаются года). Следовательно запрос может вернуть не очень логичные данные. Т.е. запрос не верен, но давать данные будет верные, отчасти от чистоты данных и правильных параметров запроса.

Бардак.
И эти люди строят наше будущее.
12 янв 14, 16:20    [15404685]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Naile
По поводу адреса - на самом деле у меня и есть отдельные таблицы для адресов.
Прошу прощения, если я всех сбила с толку, просто я хотела более "короткий" вариант показать. Я решила, что на суть вопроса это не влияет.
Просто в таблице Account есть и после Address, и всевозможноые RegionId, StateId, MuncipalityId, CityId, VillageId, Street, Building, Apartment, Zip.
И сравнения я делаю по ним...
А Address - написала для краткости.
Боже. Незачем делать сравнения по всем этим колонкам, как я и писал выше надо сравнивать по идентификатору адреса который прописан прямо в таблице клиентов, а на таблице адресов наложить условие уникальности.
Тогда у "жены первый родитель" будет тот же AddressID что и у "мужа второй родитель". На это я и рассчитывал в запросе.
12 янв 14, 16:27    [15404698]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
leov
Member

Откуда: С-Петербург
Сообщений: 616
Naile
Прошу прощения за невнятную постановку задачи.
Суть в том, что Вася в 2013 году выписал себе газету "Правда", а в 2014 году - не выписал. И он должен попасть в список!
Но! Если вдруг Васин жена заказала на 2014 год газету "Правда", и у нее такой же адрес как у Васи, то Васи в списке не должно быть.

leov
да, Вы правильно все расписали...

постановка нормальная. sql на мой взгляд очень сложно и нелогично написан

дак вот если без учета адресов то вот это вроде то что вы хотели
select AccountID
from (
  select distinct AccountID
  from Document
  where ProductId in (<Продукт1>, <Продукт2>, <Продукт3>, <Продукт4>)
    and StartDate >= '2014-01-01'
)q0
left join (
  select distinct AccountID
  from Document
  where ProductId in (<Продукт1>, <Продукт2>, <Продукт3>, <Продукт4>)
    and StartDate = '2013-01-01'
    and DueDate <= '2013-12-31'
)q1 on q1.AccountID=q0.AccountID
where q1.AccountID is null

сравнивать адреса вводимые руками по моему совершенно бессмысленно
пробелы, точки, сокращения, языки разные могут быть....
вы проверьте сначала вообще есть в базе одинаковые адреса
и еще с датами
вы видите что при таком подходе заказы с StartDate в 13 году но DueDate в 14 выпадают
12 янв 14, 16:43    [15404728]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Naile
Прощу прощения, не до конца прочитала относительно DueDate. Насчет < '2014-01-01' поняла...
Замечательно.
Naile
"Зачем тут это" - я в самых двух последних строках ограничиваю условием по документам. Иначе (почему-то???) у меня ненужные данные вылезают - возможно это ошибка внутри запроса?
FacePalm.JPG, зачем вообще в том месте таблица dbo.Document. Выкиньте её и не надо никаких потом условий.
Naile
Так или иначе, например, если я это условие не ставлю
Иначе нет таблицы - по ней не написать условия. (Оборот неверен, ошибка в размышлениях)
Условия перенесите во внутрь.
Но для меня загадка как можно "так" вывернуть запрос. Так что писать где ошибки тут долго и тяжело. Мне тяжело и лень "опускаться" до такого мышления и рассписать как же вы думали во всех деталях.
Проще написать как надо. Но если хотите могу разлится по древу - но многих уже поташнивает от этого.
Naile
И проверив клиентов, которые не попадают в 17, я не вижу у них требуемого издания...
Тут скрыта проблема - постановка задачи неверна, не нужно скрывать данные, нужно сразу предоставлять список самих подписок с данными клиентов.
Ну вот видите, оператор видит клиента, но не сразу понимает почему, и вы сами дополнительно ищите - "А да, почему же вышли эти клиенты".
12 янв 14, 16:44    [15404732]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
leov, вы не обновили топик перед отправкой поста.
LEFT JOIN тут не имеет особого смысла, и вообще так связывать через дистинкт.
NOT Exists понятнее и надёжнее. Тем более для 2005 и ниже для JOIN не работает anti-semi-join реализация.

С другой стороны вы навязываете скулю определённый вид плана запроса. Не факт что он лучше, но для 2008 и выше скуль обычно сам догадывается как лучше собирать данные через SEEK или мерджить/хешить.

Так что IMXO лучше сначала написать запрос классически и не "хинтовать", а далее уже разбираться в планах и подстраиваться, если нужно.

Я согласен что должен быть SEMI JOIN.
12 янв 14, 16:58    [15404768]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
leov
Member

Откуда: С-Петербург
Сообщений: 616
Mnior
leov, вы не обновили топик перед отправкой поста.
долго писал
Mnior
LEFT JOIN тут не имеет особого смысла, и вообще так связывать через дистинкт.
NOT Exists понятнее и надёжнее. Тем более для 2005 и ниже для JOIN не работает anti-semi-join реализация.
вот это что вообще означает? может подскажете где прочитать?
Mnior
С другой стороны вы навязываете скулю определённый вид плана запроса. Не факт что он лучше, но для 2008 и выше скуль обычно сам догадывается как лучше собирать данные через SEEK или мерджить/хешить.
вот не люблю я микрософту доверять...
то вроде умный такой, а то так затупит...
я тут программист. как сказал пусть так и делает. может не совсем оптимально но стабильно и предсказуемо
Mnior
Так что IMXO лучше сначала написать запрос классически и не "хинтовать", а далее уже разбираться в планах и подстраиваться, если нужно.

Я согласен что должен быть SEMI JOIN.
я застрял в sql2000 и даже не хочу вникать во все эти новые приблуды
хотя вероятно придется
12 янв 14, 17:16    [15404796]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
aleks2
Guest
Рискуя помешать беседе знатных теоретегов, всеж скажу тредстартеру:
проще надо быть.

declare @Products(Id int primary key clustered);

insert @Products
   <Продукт1>, <Продукт2>, <Продукт3>, <Продукт4>
   
-- 2013г
declare @AccountIds3(Id int primary key clustered);

insert @AccountIds3
  select distinct AccountId from Document d innser join @Products p on d.ProductId = p.ID
    where d.StartDate => '2013-01-01' and d.DueDate <= '2013-12-31';

declare @Addresses3(Address nvarchar(256) primary key clustered);

insert @Addresses3
  select distinct Address from Account a inner join @AccountIds3 i on i.Id = a.Id;
------------------------------ 
-- 2014г
declare @AccountIds4(Id int primary key clustered);

insert @AccountIds4
  select distinct AccountId from Document d innser join @Products p on d.ProductId = p.ID
    where d.StartDate >= '2014-01-01'

declare @Addresses4(Address nvarchar(256) primary key clustered);

insert @Addresses
  select distinct Address from Account a inner join @AccountIds4 i on i.Id = a.Id;
-------------------------------------------------
-- ... по которым найду адреса
select * from @Addresses3
except
select * from @Addresses4;

-- делаю ставку на пару секунд.
12 янв 14, 17:34    [15404841]     Ответить | Цитировать Сообщить модератору
 Re: Как составить запрос без использования IN и EXISTS?  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
aleks2 в своём стиле.

leov
вот это что вообще означает? может подскажете где прочитать?
semi-join?
10704622
Где описано о перформансе не найду, ссори.
То что есть:
Справочник по логическим и физическим операторам Showplan
Left Anti Semi Join (MS SQL 2000)
leov
вот не люблю я микрософту доверять...
то вроде умный такой, а то так затупит...
Зря. Надо понять и простить почему он тупит. Оказывается в большей части от того что мы от него скрываем важные детали. А далее можно наработать навыки как это недопустить и как стабилизировать запросы (без их полного переписывания).
В итоге в основном выполняется правило что и задача описана лучшим образом и работает правильно. Да и скуль так иногда подсказывает что форма записи не верна и потом понимаешь почему.
leov
я застрял в sql2000
Жаль, хоть где-то стало хуже, но в некоторых стало получше в новых версиях.
leov
и даже не хочу вникать во все эти новые приблуды
Это не новые приблуды - semi как реальная реализация в планах есть и в 2000м. Как логический оператор языка - нет и в помине.
12 янв 14, 20:39    [15405383]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить