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

Откуда:
Сообщений: 9
Признаться, со своим вопросом даже не знал, как правильно тему написать.

Для отчёта создаётся временная табличка-календарик со списком дат и количеством пападаний.
Для примера:
declare @temp table (D date, X int default 0)
insert into @temp 
  (D)
  values 
  ('01.01.18'),
  ('02.01.18'),
  ('03.01.18'),
  ('04.01.18'),
  ('05.01.18'),
  ('06.01.18')


Есть другая табличка в которой имеются записи с указанием периода работы. Начальная и конечная даты.
create table periods (S date, E date)
insert into periods
  values
  ('25.10.17', '05.01.18'),
  ('20.04.16', '30.10.17'),
  ('02.01.18', '05.01.18'),
  ('08.01.18', '09.01.18'),
  ('03.01.18', '10.01.18')

Записей сотни тысяч за несколько лет. Они могут полностью попадать в расчётный период или частично. Или вообще не попадать:

Хочется узнать, есть ли элегантный способ обновления временной таблички при такой ситуации?
Что бы для каждого дня подсчитать количество записей, попавших в диапазон?
Не считая варианта с курсором в голову приходи такой вариант:
update t
  set X = (select count(*) from periods where t.D between S and E)	
  from @temp t


Но это хорошо для такого простого варианта. А когда реальный подзапрос состоит не из одной таблички, а из множества связанных с большим количеством условий, то такой вариант уже работает очень тяжело. Особенно когда надо сделать выборку за несколько месяцев.
Как вариант сперва попробовать нужные записи из этой выборки вытащить ещё в одну временную табличку и уже потом её использовать в подзапросе.

Но мне интересно, может быть есть какой-то более простой способ всё это подсчитать не делая подзапросы по каждому дню отдельно?
10 янв 18, 08:35    [21092101]     Ответить | Цитировать Сообщить модератору
 Re: Обновить таблицу со списком дат количеством попаданий этих дат из диапазонов другой  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20492
Maestro NV
такой вариант уже работает очень тяжело

А что там с индексами на таблицах? Если их нет (как показано) - то как ни делай, всё одно хреново получится. А если их есть - то надо верстать решение в зависимости от того, каких именно их есть.
10 янв 18, 09:12    [21092187]     Ответить | Цитировать Сообщить модератору
 Re: Обновить таблицу со списком дат количеством попаданий этих дат из диапазонов другой  [new]
Добрый Э - Эх
Guest
Maestro NV,

почитай про Merge.
10 янв 18, 09:19    [21092206]     Ответить | Цитировать Сообщить модератору
 Re: Обновить таблицу со списком дат количеством попаданий этих дат из диапазонов другой  [new]
Добрый Э - Эх
Guest
Maestro NV,

в твоем исходном тестовом примере решение могло бы выглядеть примерно так:

merge into @temp d
using (
        select t.D, count(1) as cnt
          from @temp t
          join periods p
            on t.d between p.s and p.e
         group by t.d
      ) s
   on (d.d = s.d)
 when matched 
   then update set d.x = s.cnt;
10 янв 18, 09:36    [21092283]     Ответить | Цитировать Сообщить модератору
 Re: Обновить таблицу со списком дат количеством попаданий этих дат из диапазонов другой  [new]
Maestro NV
Member

Откуда:
Сообщений: 9
Добрый Э - Эх
Maestro NV,

почитай про Merge.


Спасибо за наводку. Как-то так получилось, что про merge ничего и не знаю.
Надо изучить.
10 янв 18, 11:45    [21092820]     Ответить | Цитировать Сообщить модератору
 Re: Обновить таблицу со списком дат количеством попаданий этих дат из диапазонов другой  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
+ Для дат используйте ISO написание, не зависящее от языковых настроек
SET DATEFORMAT mdy
DECLARE @date11 DATE
DECLARE @date12 DATE
DECLARE @date13 DATE
DECLARE @date2 DATETIME2(7)
DECLARE @date3 DATETIME
SET @date11 = '01.02.18' -- интерпретация зависит от языковых настроек и SET DATEFORMAT
SET @date12 = '20180201' -- ISO для DATE/DATETIME/DATETIME2
SET @date13 = '2018-02-01' -- ISO для DATE/DATETIME2
SET @date2 = '2018-02-01T00:00:00.0000000' -- ISO DATETIME2
SET @date3 = '2018-02-01T00:00:00.000' -- ISO DATETIME
SELECT @date11, @date12, @date13, @date2, @date3
10 янв 18, 11:49    [21092841]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить