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

Откуда:
Сообщений: 61
Существует выборка:
Договор 1 01.01.2002 1000
Договор 1 01.02.2002 1000
Договор 1 01.03.2002 1000
Договор 1 01.04.2002 500
Договор 1 01.05.2002 400
Договор 2 01.01.2002 3000
Договор 2 01.02.2002 3000
Договор 2 01.03.2002 3000
Договор 2 01.04.2002 1000
Договор 3 01.01.2002 2000
Договор 3 01.02.2002 2000
Договор 3 01.03.2002 2000
Договор 3 01.04.2002 1000
Договор 3 01.05.2002 1000
Договор 3 01.06.2002 1000


Необходимо выводить записи в таком виде:
Договор 1 01.01.2002 1000 (число на текущую дату) 1000 (число на следующую дату +1 месяц)
Договор 1 01.02.2002 1000 (число на текущую дату) 1000 (число на следующую дату +1 месяц)
Договор 1 01.03.2002 1000 (число на текущую дату) 500 (число на следующую дату +1 месяц)
Договор 1 01.04.2002 500 (число на текущую дату) 400 (число на следующую дату +1 месяц)
Договор 1 01.05.2002 400 (число на текущую дату) null (число на следующую дату +1 месяц)
Договор 2 01.01.2002 3000 (число на текущую дату) 3000 (число на следующую дату +1 месяц)
Договор 2 01.02.2002 3000 (число на текущую дату) 3000 (число на следующую дату +1 месяц)
Договор 2 01.03.2002 3000 (число на текущую дату) 1000 (число на следующую дату +1 месяц)
Договор 2 01.04.2002 1000 (число на текущую дату) null (число на следующую дату +1 месяц)

и т.д.

я так понимиаю что то с datediff(month,@date1, @date2)=1 , возможно какие то более логичные варианты.
20 мар 14, 12:07    [15758241]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2423
CheaterX,

если версия сиквела позволяет то используйте lead иначе apply еще иначе вложенный запрос с min
20 мар 14, 12:28    [15758464]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
_djХомяГ
Guest
Еслм версия >=2005
1 Пронумеровать записи ROW_NUMBER () over (partition by [Договор] order by [Дата]) as RN
2 Поджойнить даблицу саму с собой по равенству договора и таблица1.RN+1= таблица2.RN
20 мар 14, 12:35    [15758544]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2423
_djХомяГ
Еслм версия >=2005
1 Пронумеровать записи ROW_NUMBER () over (partition by [Договор] order by [Дата]) as RN
2 Поджойнить даблицу саму с собой по равенству договора и таблица1.RN+1= таблица2.RN


да, про row_number я забыл, хотя тут еще вопрос, что будет быстрее, outer apply с top 1 или нумерация с join
20 мар 14, 12:45    [15758679]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
_djХомяГ
Guest
set dateformat dmy
declare @t table (ContractID int,Date datetime,Qty int )
insert into @t 
select 1,'01.01.2002',1000
union all 
select 1,'01.02.2002',500
union all 
select 1,'01.03.2002',3
union all 
select 2,'01.01.2002',3000
union all
select 2,'01.02.2002',1000

;with cte 
as
(
  select *,row_number()  over (partition by ContractID order by Date ) as RN from @t
)
select t1.ContractID,t1.Date,t1.Qty,t2.Qty 
from cte t1 left join cte t2 
on t1.ContractID=t2.ContractID and t1.RN+1=t2.RN

А на вопрос что быстрее - смотрите планы
20 мар 14, 12:48    [15758699]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
CheaterX
Member

Откуда:
Сообщений: 61
WarAnt,_djХомяГ

Спасибо, но если можно примеры. Хотелось бы в 1 селект засунуть, не используя никакие переменные. Apply никогда не пользовался. Буду благодарен за пример.
20 мар 14, 12:52    [15758736]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2423
CheaterX
WarAnt,_djХомяГ

Спасибо, но если можно примеры. Хотелось бы в 1 селект засунуть, не используя никакие переменные. Apply никогда не пользовался. Буду благодарен за пример.


у _djХомяГ пример без переменной, то что вы видите это он з авас заполнил тестовые данные и использовал переменную таблицу

пример с outer apply

set dateformat dmy
declare @t table (ContractID int,Date datetime,Qty int )
insert into @t 
select 1,'01.01.2002',1000
union all 
select 1,'01.02.2002',500
union all 
select 1,'01.03.2002',3
union all 
select 2,'01.01.2002',3000
union all
select 2,'01.02.2002',1000

select ContractID, Date, t.Qty, n.Qty
from  @t t outer apply (select top 1 Qty from @t where ContractID = t.ContractID and Date > t.Date order by Date) n
20 мар 14, 12:57    [15758785]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
_djХомяГ
Guest
просто subquery
select *,(select top 1 Qty from @t t1 where t1.ContractID=t.ContractID and t1.Date>t.Date order by t1.Date)
from @t t
20 мар 14, 12:59    [15758802]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
CheaterX
Member

Откуда:
Сообщений: 61
_djХомяГ,

Спасибо большое)
20 мар 14, 13:16    [15758998]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
Avangard1987
Member

Откуда:
Сообщений: 15
А я бы функцию Lead использовал, хотя не знаю на вашей СУБД она есть или нет.
Просто: рассматриваем группы строк, где одинаковый номер договора, и смотрим следующую запись в группе.
SELECT ColumnName,
           ColumnDate,
           ColumnMoney,
           Lead( ColumnMoney ) OVER( PARTITION BY ColumnName ORDER BY ColumnDate ) AS NextMonthValue
FROM   TableName
20 мар 14, 14:01    [15759581]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
CheaterX
Member

Откуда:
Сообщений: 61
Avangard1987,
2008 R2 Enterprise у меня

Вот еще дополнение к задачи:
Договор 1 01.01.2002 1000
Договор 1 01.02.2002 1000
Договор 1 01.03.2002 1000
Договор 1 01.04.2002 500
Договор 1 01.05.2002 400
Договор 2 01.01.2002 3000
Договор 2 01.02.2002 3000
Договор 2 01.03.2002 3000
Договор 2 01.04.2002 1000
Договор 3 01.01.2002 2000
Договор 3 01.02.2002 2000
Договор 3 01.03.2002 2000
Договор 3 01.04.2002 1000
Договор 3 01.05.2002 1000
Договор 3 01.06.2002 1000
Договор 4 01.01.2002 2000
Договор 4 01.02.2002 2000
Договор 4 01.03.2002 2000
Договор 4 01.04.2002 2000
Договор 4 01.05.2002 2000
Договор 4 01.06.2002 2000

по договору 4 изменений не было, как отсечь его?

сейчас использую предложенный _djХомяГ subquery (в таблице 300к записей, отрабатывает за 15 секунд)
20 мар 14, 14:58    [15760122]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2423
CheaterX
Avangard1987,
2008 R2 Enterprise у меня



по договору 4 изменений не было, как отсечь его?

сейчас использую предложенный _djХомяГ subquery (в таблице 300к записей, отрабатывает за 15 секунд)


t.Qty != t1.Qty
20 мар 14, 16:08    [15760770]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с соединением одной таблицы.  [new]
CheaterX
Member

Откуда:
Сообщений: 61
WarAnt,

Спасибо. Но в этом случае он не выдает записи
Договор 1 01.01.2002 1000
Договор 1 01.02.2002 1000
Договор 1 01.03.2002 1000

а мне нужно чтобы он выдавал договора у которых были хоть когда то изменения. И не выводил только те у которых никогда не было изменений.
21 мар 14, 08:53    [15763897]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить