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

Откуда:
Сообщений: 78
Есть две таблицы с одинаковыми первичными ключами, например:
create table #t1

(
Field1 int,
Field2 varchar(20),
TheDate datetime,
Info1 float,
primary key (Field1,Field2,TheDate)
)

create table #t2
(
Field1 int,
Field2 varchar(20),
TheDate datetime,
Info2 float,
primary key (Field1,Field2,TheDate)
)

В #t1 заносятся данные по определенным значениям полей Field1 и Field2 на каждую дату, а в #t2 - по тем же значениям Field1 и Field2, но только на некоторые даты (например, на начало месяцев). Надо для каждой записи в #t1 найти запись в #t2 с теми же значениями Field1 и Field2 и максимальной датой, меньшей TheDate в #t1.
Делаю так:
select *

from #t1 as t1
left join #t2 as t2 on t2.Field1 = t1.Field1 and t2.Field2 = t1.Field2 and t2.TheDate =
(select max(TheDate) from #t2
where Field1 = t1.Field1 and Field2 = t1.Field2 and TheDate<=t1.TheDate)

Работает правильно, но уж больно медленно. Нет ли способа побыстрее?
10 июл 03, 16:30    [257712]     Ответить | Цитировать Сообщить модератору
 Re: join по '<='  [new]
LAU
Guest
А так :

select *
from #t1 as t1
left join #t2 as t2 on t2.Field1 = t1.Field1 and t2.Field2 = t1.Field2
where t2.TheDate = ( select max(TheDate) from #t2
where TheDate<=t1.TheDate)
10 июл 03, 17:39    [257822]     Ответить | Цитировать Сообщить модератору
 Re: join по '<='  [new]
Glory
Member

Откуда:
Сообщений: 104760
select t1.Field1, t1.Field2, t1.TheDate, t2.Field1, t2.Field2, MAX(t1.TheDate)

from #t1 as t1
left join #t2 as t2 on t2.Field1 = t1.Field1 and t2.Field2 = t1.Field2 and t2.TheDate <= t1.TheDate
GROUP BY t1.Field1, t1.Field2, t1.TheDate, t2.Field1, t2.Field2
10 июл 03, 17:40    [257826]     Ответить | Цитировать Сообщить модератору
 Re: join по '<='  [new]
LAU
Guest
запрос Glory лучший по Execution Plan
10 июл 03, 18:00    [257852]     Ответить | Цитировать Сообщить модератору
 Re: join по '<='  [new]
Koloto
Member

Откуда:
Сообщений: 78
To LAU
В таком варианте при выборе даты из #t2 не учитываются значения Field1 и Field2, а в зависимости от них макс. дата может быть различной. Например, по каким-то значениям Field1, Field2 за какой-то месяц может вообще не быть значений или наоборот дополнительные значения в середине месяца.

To Glory.
Таким запросом можно найти только соответствующие макс. даты, а нужно также знать значения полей #t1.Info1 и #t2.Info2. Можно, конечно, и по ним сгруппировать, но это будет уже слишком. К тому же в реальной задаче в первая таблица - это достаточно сложный подзапрос, в котором порядка 15 полей. Такая группировка будет совсем тормзной и ресурсоемкой.
И почему ты группируешь по t1.Field1, t1.Field2, t1.TheDate, t2.Field1, t2.Field2, а не только по t1.Field1, t1.Field2, t1.TheDate?
10 июл 03, 18:06    [257859]     Ответить | Цитировать Сообщить модератору
 Re: join по '<='  [new]
Glory
Member

Откуда:
Сообщений: 104760
И почему ты группируешь по t1.Field1, t1.Field2, t1.TheDate, t2.Field1, t2.Field2, а не только по t1.Field1, t1.Field2, t1.TheDate?

Да, можно только по t1.Field1, t1.Field2, t1.TheDate

Таким запросом можно найти только соответствующие макс. даты, а нужно также знать значения полей #t1.Info1 и #t2.Info2. Можно, конечно, и по ним сгруппировать, но это будет уже слишком.

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

ЗЫ
Вот кстати пример для демонстрации недостатков составного первичного ключа :)
10 июл 03, 18:21    [257882]     Ответить | Цитировать Сообщить модератору
 Re: join по '<='  [new]
LAU
Guest
Koloto так думаешь или проверял ?
To LAU
В таком варианте при выборе даты из #t2 не учитываются значения Field1 и Field2, а в зависимости от них макс. дата может быть различной.
Например, по каким-то значениям Field1, Field2 за какой-то месяц может вообще не быть значений В таком случае твой запрос выдаст поля #t2 со
значением NULL ,а мой не вернет как не попавшие под условие


или наоборот дополнительные значения в середине месяца.

я добавил несколько значений в #t2 - твой и мой запрос вернули одинаковое знеачение строк

Попробуй - увидишь
10 июл 03, 18:39    [257902]     Ответить | Цитировать Сообщить модератору
 Re: join по '<='  [new]
Koloto
Member

Откуда:
Сообщений: 78
To Glory
Ну так первичный ключ-то у нас в запросе есть - соединяем результаты запроса с таблицами и ....
Это тоже громоздко получается. Сначала вычисляем все данные из #t1 и нужные даты из #t2. Потом все это опять join-им с #t2 и вычисляем данные из этой этой таблицы. Т.е. предварительные результаты надо куда-то запихнуть, например, во временную табличку. Или делать это через немеренный подзапрос... Если учесть, что #t1 в моем случае - это тоже подзапрос, который занимает строк 20 и вычисляется порядка минут пяти, то... Да я сам через месяц в этом не разберусь

To LAU
В таком случае твой запрос выдаст поля #t2 со
значением NULL ,а мой не вернет как не попавшие под условие

Виноват, не оговорил условие. Мне в этом случае и надо, чтобы возвратилось NULL. Отсюда и left join, а не inner join.

я добавил несколько значений в #t2 - твой и мой запрос вернули одинаковое знеачение строк
Попробуй - увидишь

Пробуем и смотрим:
create table #t1

(
Field1 int,
Field2 varchar(20),
TheDate datetime,
Info1 float,
primary key (Field1,Field2,TheDate)
)

create table #t2
(
Field1 int,
Field2 varchar(20),
TheDate datetime,
Info2 float,
primary key (Field1,Field2,TheDate)
)

insert into #t1 values(1,'111','20030601',11.1)
insert into #t1 values(1,'111','20030602',11.2)
insert into #t1 values(1,'111','20030603',11.3)
insert into #t1 values(2,'222','20030601',12.1)
insert into #t1 values(2,'222','20030602',12.2)
insert into #t1 values(2,'222','20030603',12.3)
insert into #t1 values(1,'111','20030701',21.1)
insert into #t1 values(1,'111','20030702',22.2)
insert into #t1 values(1,'111','20030703',23.3)
insert into #t1 values(2,'222','20030701',22.1)
insert into #t1 values(2,'222','20030702',22.2)
insert into #t1 values(2,'222','20030703',22.3)

insert into #t2 values(1,'111','20030601',110)
insert into #t2 values(2,'222','20030601',120)
insert into #t2 values(1,'111','20030701',210)
insert into #t2 values(2,'222','20030701',220)
insert into #t2 values(2,'222','20030703',230)

--мой запрос

select *
from #t1 as t1
left join #t2 as t2 on t2.Field1 = t1.Field1 and t2.Field2 = t1.Field2 and t2.TheDate =
(select max(TheDate) from #t2
where Field1 = t1.Field1 and Field2 = t1.Field2 and TheDate<=t1.TheDate)

--твой запрос

select *
from #t1 as t1
left join #t2 as t2 on t2.Field1 = t1.Field1 and t2.Field2 = t1.Field2
where t2.TheDate = ( select max(TheDate) from #t2
where TheDate<=t1.TheDate)

--твой запрос, где условие where включено в left join

select *
from #t1 as t1
left join #t2 as t2 on t2.Field1 = t1.Field1 and t2.Field2 = t1.Field2
and t2.TheDate = ( select max(TheDate) from #t2
where TheDate<=t1.TheDate)
drop table #t1
drop table #t2

Сравни результаты и убедись, что запросы работают не одинаково. Запрос собственноручно оттестил, так что просто копируй и запускай в QA.
11 июл 03, 09:50    [258229]     Ответить | Цитировать Сообщить модератору
 Re: join по '<='  [new]
LAU
Guest
пардон ,допустил лажу , думал что из подзапроса "видно" (учитывается ) условия left join - ан нет
Что получается если я буду писать запрос с скажем 3 подрапросами для
связных left(right) join таблиц то прийдется в каждом подзапросе дублировать
условия join ? Плохо :)

Возможно единственный путь ускорить выполнение запроса - поменять структуру таблиц - т.е. добавить некий ID primary key , а от сотавного
первичного ключа отказаться
Что даст ? условия по join будет только по одному ключевому полю ,
а это быстрее чем по двум полям из составного первичного ключа + умножить
разницу на 2 так как есть подзапрос где условие должно дублироваться

вот такие пирожки :(
11 июл 03, 14:54    [258890]     Ответить | Цитировать Сообщить модератору
 Re: join по '<='  [new]
Koloto
Member

Откуда:
Сообщений: 78
To LAU
Что получается если я буду писать запрос с скажем 3 подрапросами для
связных left(right) join таблиц то прийдется в каждом подзапросе дублировать
условия join ? Плохо :)


Придется дублировать. И это отвратительно;-)

Возможно единственный путь ускорить выполнение запроса - поменять структуру таблиц - т.е. добавить некий ID primary key

Не думаю, что это даст большой выигрыш. Может процентов 10-20, но это не принципиально. Хотя я, конечно, не тестил Неохота из-за этого все запросы к этим таблицам переписывать:)
11 июл 03, 15:13    [258940]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить