SQL генерирующая таблица, которая показывает промежуток времени между определенным набором событий - PullRequest
2 голосов
/ 05 февраля 2020

Я ищу способ извлечь таблицу, которая показывает даты между определенными событиями. Я думал о Partition By в сочетании с контрольной таблицей для выполнения этой работы.

У меня есть следующая таблица со всеми транзакциями

enter image description here

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

enter image description here

Теперь вопрос состоит в том, возможно ли получить простой и быстрый оператор SQL, который путем объединения этих двух таблиц может произвести следующий ввод. Выходные данные содержат найденные тогда комбинации значений fromdate и todate для каждого сотрудника и области с использованием контрольной таблицы, чтобы в конечном итоге вычислить DATEDIFF между событиями, как показано ниже:

enter image description here

    CREATE TABLE [dbo].[Fact](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [PersonID] [nvarchar](255) NULL,
    [PersonName] [nvarchar](255) NULL,
    [Area] [nvarchar](255) NULL,
    [EventID] [nvarchar](255) NULL,
    [Date] [date] NULL
    )
GO

    CREATE TABLE [dbo].[ControlTable](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [EventSequenceID] [nvarchar](255) NULL,
    [EventSequenceName] [nvarchar](255) NULL,
    [FromEvent] [nvarchar](255) NULL,
    [ToEvent] [nvarchar](255) NULL
)
GO

INSERT [dbo].[ControlTable] ([EventSequenceID], [EventSequenceName], [FromEvent], [ToEvent]) VALUES (N'1', N'Event E-> H', N'Event E', N'Event H')
GO
INSERT [dbo].[ControlTable] ([EventSequenceID], [EventSequenceName], [FromEvent], [ToEvent]) VALUES (N'2', N'Event K to H', N'Event K', N'Event H')
GO
INSERT [dbo].[ControlTable] ([EventSequenceID], [EventSequenceName], [FromEvent], [ToEvent]) VALUES (N'3', N'Event E to Event T', N'Event E', N'Event T')
GO

INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'1', N'Peter', N'Area X', N'Event E', CAST(N'2000-01-01' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'1', N'Peter', N'Area X', N'Event B', CAST(N'2000-01-03' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'1', N'Peter', N'Area X', N'Event K', CAST(N'2000-01-06' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'1', N'Peter', N'Area X', N'Event A', CAST(N'2000-01-09' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'1', N'Peter', N'Area X', N'Event H', CAST(N'2000-01-12' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'2', N'Lis', N'Area X', N'Event E', CAST(N'2000-01-01' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'2', N'Lis', N'Area X', N'Event K', CAST(N'2000-01-05' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'2', N'Lis', N'Area X', N'Event C', CAST(N'2000-01-06' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'2', N'Lis', N'Area X', N'Event H', CAST(N'2000-01-11' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'2', N'Lis', N'Area X', N'Event T', CAST(N'2000-01-28' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'2', N'Lis', N'Area B', N'Event E', CAST(N'2000-03-10' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'2', N'Lis', N'Area B', N'Event G', CAST(N'2000-03-14' AS Date))
GO
INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'2', N'Lis', N'Area B', N'Event H', CAST(N'2000-03-20' AS Date))
GO

Может быть несколько событий в пределах одного человека / области, например, добавление следующей строки означает, что есть два «события H» для Питера и области X

  INSERT [dbo].[Fact] ([PersonID], [PersonName], [Area], [EventID], [Date]) VALUES (N'1', N'Peter', N'Area X', N'Event H', CAST(N'2000-01-24' AS Date))

, поэтому в качестве конечного результата выходные данные могут включать ранг события from / to, например enter image description here

1 Ответ

1 голос
/ 05 февраля 2020

Предполагая, что одно и то же событие никогда не появляется дважды для одного и того же кортежа person/area, вы можете присоединиться к таблице и выполнить условное агрегирование:

select
    ct.eventSequenceId,
    ct.eventSequenceName,
    f.personID,
    f.personName,
    f.area,
    min(case when f.eventID = ct.fromEvent then f.date end) fromDate,
    min(case when f.eventID = ct.toEvent then f.date end) toDate,
    datediff(
        day, 
        min(case when f.eventID = ct.fromEvent then f.date end),
        min(case when f.eventID = ct.toEvent then f.date end)
    ) dateDifference
from fact f
inner join controltable ct 
    on f.eventID in (ct.fromEvent, ct.toEvent)
group by
    ct.eventSequenceId,
    ct.eventSequenceName,
    f.personID,
    f.personName,
    f.area

с количеством (*)> 1 порядка по f.personID , ct.eventSequenceId

Предложение having отфильтровывает частичные совпадения (ie найдено одно событие, но нет другого).

Демонстрация на DB Fiddle :

eventSequenceId | eventSequenceName  | personID | personName | area   | fromDate   | toDate     | dateDifference
:-------------- | :----------------- | :------- | :--------- | :----- | :--------- | :--------- | -------------:
1               | Event E-> H        | 1        | Peter      | Area X | 2000-01-01 | 2000-01-12 |             11
2               | Event K to H       | 1        | Peter      | Area X | 2000-01-06 | 2000-01-12 |              6
1               | Event E-> H        | 2        | Lis        | Area B | 2000-03-10 | 2000-03-20 |             10
1               | Event E-> H        | 2        | Lis        | Area X | 2000-01-01 | 2000-01-11 |             10
2               | Event K to H       | 2        | Lis        | Area X | 2000-01-05 | 2000-01-11 |              6
3               | Event E to Event T | 2        | Lis        | Area X | 2000-01-01 | 2000-01-28 |             27
...