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

Откуда: РБ, Нефтекамск
Сообщений: 27
Доброго времени суток!
Прошу прощения, за "детский", наверно, вопрос:

есть таблица t1

vcode1, car1, date1, date2
vcode2, car1, date3, date4
vcode3, car1, date5, date6

есть другая табличка t2, "сводка" за месяц по каждой машине, где указаны литры заправки

car1, d1, d2, d3, d4, d5, ... d31
car2, d1, d2, d3, d4, d5, ... d31

где, каждый d1, d2 - это день в месяце

Нужно написать вставку в третью таблицу, чтобы на каждую машину, если d1 <> 0, то вставлялась новая строка, до соответствующей date2:

Думаю, что можно вот так попробовать:

открыть курсор1 = car1

i = day(date1)
while i <= date2
если d[i] <> 0, тогда insert ......
end
закрыть курсор1


Но очень надеюсь, что посоветуете более умный способ. Хочу начать думать "наборами данных"
20 окт 14, 12:31    [16730346]     Ответить | Цитировать Сообщить модератору
 Re: Как построить запрос без цикла и курсора?  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4902
Вам нужна вспомогательная таблица со списком дат

сначала можно сделать нумерованный список

https://www.sql.ru/forum/1112663/numerovannyy-spisok?hl=n100

потом с помощью dateadd превратить его в даты и сохранить это в физическую таблицу с индексом

затем вам нужно сделать запрос из вашей таблицы

FROM ваша таблица T
OUTER APPLY 
(
SELECT DT FROM список дат 
WHERE DT BETWEEN T.Date1 AND T.date2
) X
20 окт 14, 12:39    [16730395]     Ответить | Цитировать Сообщить модератору
 Re: Как построить запрос без цикла и курсора?  [new]
aleks2
Guest
Liana2509
Нужно написать вставку в третью таблицу, чтобы на каждую машину, если d1 <> 0, то вставлялась новая строка, до соответствующей date2:

Но очень надеюсь, что посоветуете более умный способ. Хочу начать думать "наборами данных"


Для начала надо научиться просто думать.

Вас все остальные дни, окромя d1, не интересуют?
20 окт 14, 13:00    [16730563]     Ответить | Цитировать Сообщить модератору
 Re: Как построить запрос без цикла и курсора?  [new]
Liana2509
Member

Откуда: РБ, Нефтекамск
Сообщений: 27
aleks2, если научите думать, буду благодарна )

интересуют все дни, поэтому while их перебирает
20 окт 14, 13:30    [16730782]     Ответить | Цитировать Сообщить модератору
 Re: Как построить запрос без цикла и курсора?  [new]
aleks2
Guest
Как-то так...
;with
cardays as ( select car, 1 as day, d1 as d from [другая табличка t2]
             union  
             select car, 2 as day, d2 as d from [другая табличка t2]   
             ...
             union  
             select car, 31 as day, d31 as d from [другая табличка t2]                
            ) -- в следующий раз думайте над нормализацией.
toinsert as ( select * from cardays cd
                 where d <> 0 
                 and day between day(@date1) and day(@date2)
                 and not exists( select * from [третью таблицу] where car = cd.car and [Date] = @date1 - day(@date1)+ day )
             )
insert [третью таблицу]( car, d, [date] )
  select car, d, @date1 - day(@date1)+ day;
20 окт 14, 14:10    [16731121]     Ответить | Цитировать Сообщить модератору
 Re: Как построить запрос без цикла и курсора?  [new]
Liana2509
Member

Откуда: РБ, Нефтекамск
Сообщений: 27
a_voronin, спасибо большое! сразу не поняла с "OUTER APPLY" как работать. сделала, как написал ниже aleks2. Потом поняла, что у Вас идея "повернуть" таблицу общая ) Спасибо!
22 окт 14, 09:38    [16741261]     Ответить | Цитировать Сообщить модератору
 Re: Как построить запрос без цикла и курсора?  [new]
Liana2509
Member

Откуда: РБ, Нефтекамск
Сообщений: 27
aleks2, Спасибо огромное! не получилось воспроизвести Ваш синтаксис, но идея супер! )

 insert  #cardays(PodvSostav, day1, d, voditel)
           ( select PodvSostav, 1 as day, d1 as d, voditel from SvodkaTehnPDocMat where pcode = @vcode and PodvSostav = @Svodkacar and voditel = @Svodkavoditel
             union  
             select PodvSostav, 2 as day, d2 as d, voditel from SvodkaTehnPDocMat where pcode = @vcode and PodvSostav = @Svodkacar and voditel = @Svodkavoditel
             ...............
             union
             select PodvSostav, 31 as day, d31 as d, voditel from SvodkaTehnPDocMat where pcode = @vcode and PodvSostav = @Svodkacar and voditel = @Svodkavoditel
            
 ) -- в следующий раз думайте над нормализацией.


insert  #wert(sklad, PodvSostav, day1, d, voditel, pcode)
 select sklad = @sklad, cd.PodvSostav, cd.day1, cd.d, cd.voditel, p.vcode 
   from #cardays cd left join PdAuto p on cd.podvsostav = p.car
                 where cd.d <> 0 
                 and day1 between day(p.dateOut) and day(p.dateIn)
                 and cd.voditel = p.voditel


все работает.

P.S. надеюсь, научусь тоже думать ) Спасибо еще раз!
22 окт 14, 09:47    [16741312]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить