Сложная работа с диапазонами дат - MS Access / SQL - PullRequest
0 голосов
/ 05 ноября 2018

У меня есть небольшая хитрая работа, которая включает вычисление перекрытия между определенными диапазонами дат. Я написал немного кода в VBA / Excel, который прекрасно работает, но он ужасно медленный - и я думаю, что такого рода вещи принадлежат Access (или подобному), а не Excel в любом случае.

Очень краткое изложение того, что нужно делать ...

Иметь основную таблицу (может быть миллионы строк), которая выглядит примерно так:

Main_Table

  • Account_Number_Index
  • Дата_начала
  • датой_окончания
  • Data_Item_1
  • Data_Item_2 ... ... ...
  • Data_Item_N

У меня также есть небольшая таблица "периодов анализа" (обычно только 4-6 строк)

Analysis_Periods

  • Period_Index
  • Period_Start_Date
  • Period_End_Date
  • Period_Label

Мне нужно создать выходную таблицу из всего этого, которая имеет одну запись для каждой комбинации Account_Number_Index и Period_Index. Поля будут:

Output_Table

  • Account_Number_Index
  • Overlap_Start_Date (поясняется ниже)
  • Overlap_End_Date (поясняется ниже)
  • Period_Index
  • Data_Item_1
  • Data_Item_2 ... ... ...
  • Data_Item_N

Так что в свободном псевдокоде это будет выглядеть примерно так:

For each row in Main_Table

    For each row in Analysis_Periods

        Work out the overlapping period (Overlap_Start_Date...Overlap_End_Date) for time intervals (Start_Date...End_Date) and (Period_Start_Date...Period_End_Date)

        If there is no overlap at all

            Do nothing

        Else

            Output a row of data to Output_Table which is identical to the row in the Main_Table except that:
                 * Overlap_Start_Date used instead of Start_Date
                 * Overlap_End_Date used instead of End_Date
                 * Period_Index and Period_Label tagged also output

         End If

    Next row in Analysis_Periods

Next row in Main_Table

Вычисление периода перекрытия - это всего лишь случай временного интервала между: (a) max (Start_Date, Period_Start_Date) (b) мин (конечная дата, период_ конечная дата)

Я думаю, что мне удалось включить гиперссылку внизу, чтобы немного нацарапать на бумаге: пересекающиеся временные интервалы, если это помогает визуализировать проблему.

Может кто-нибудь предложить эффективный способ сделать это в Access, пожалуйста, с помощью некоторого кода SQL или некоторого VBA (или обоих)?

Я не эксперт в этом деле, поэтому надеюсь, что в этом есть смысл ... извиняюсь, если нет.

Самый благодарный за любую помощь.

Thx A

https://i.stack.imgur.com/Al3pO.jpg

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Рассмотрим отфильтрованную CROSS JOIN между обеими таблицами, где вы помещаете таблицы в разделенный запятыми список в предложении FROM без каких-либо JOIN, за которыми следует WHERE в датах. Затем поместите запрос в условный агрегат GROUP BY для необходимых MIN и MAX по датам.

SELECT m.Account_Number_Index, 
       p.Period_Index, 
       MIN(IIF(m.Start_Date < a.Period_Start_Date, 
               m.Start_Date, a.Period_Start_Date)) AS Overlap_Start_Date,
       MAX(IIF(m.End_Date < a.Period_End_Date, 
               a.Period_End_Date, m.End_Date)) As Overlap_End_Date

FROM MainTable m, AnalysisPeriods a
WHERE m.Start_Date <= a.Period_Start_Date 
  AND a.Period_End_Date <= m.End_Date
GROUP BY m.Account_Number_Index, 
         p.Period_Index

И во втором запросе присоедините исходные таблицы к этому запросу в индексных полях. Даже подумайте о создании временной таблицы overlap_table (с предложением SELECT ... INTO) и использовании вместо запроса:

SELECT m.Account_Number_Index, 
       p.Period_Index, 
       q.Overlap_Start_Date, 
       q.Overlap_End_Date
       p.Period_Label,
       m.Data_Item_1,
       m.Data_Item_2,
       m.Data_Item_3, 
       ...
       m.Data_Item_n

FROM (overlap_query_or_table q
INNER JOIN MainTable m 
  ON q.Account_Number_Index = m.Account_Number_Index)
INNER JOIN AnalysisPeriods a
  ON q.Period_Index = p.Period_Index

ПРИМЕЧАНИЕ : эта обработка включает в себя перекрестное соединение, которое возвращает декартово произведение между обеими таблицами (т.е. ~ 1 миллион строк X 5-6 строк), поэтому эффективность не гарантируется.

0 голосов
/ 05 ноября 2018

Если вы используете доступ, почему бы вам не использовать запрос на соединение? Что-то похожее

Select m.Account_Number_Index, m.Start_Date,m.End_Date, ap.Period_Index, ap.Period_Lable,
m.Data_Item_1, m.Data_Item_2 ... ... ... m.Data_Item_N
From Analysis_Periods as ap left join Main_Table as m on (m.Start_Date >= ap.Period_Start_Date and m.End_date <= ap.Period_End_Date)

Для правильного начала и конца перекрытия используйте функцию iif.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...