Нахождение ближайшего времени с сопоставлением нескольких столбцов (SQL) - PullRequest
0 голосов
/ 07 июня 2018

У меня есть две таблицы: таблица 1 - это доступ к зданию в определенное время, дата, имя

Accesses

    |  Date      |    Time      | Name | accesses|
    -----------------------------------------------
    | 2018-10-10 |  10:10:34.00 |  JA  |     1   | 
    | 2018-10-10 |  10:14:10.10 |  AA  |     1   |
    | 2018-10-10 |  12:15:00.45 |  BE  |     1   |
    | 2018-10-10 |  15:00:00.50 |  JA  |     1   |
    | 2018-10-10 |  16:56:56.15 |  BE  |     1   |

И таблица 2 показывает, были ли сбои во время определенного доступа

Failure

    |  Date      |    Time      | Name | failure |
    -----------------------------------------------
    | 2018-10-10 |  10:10:40.00 |  JA  |     1   | 
    | 2018-10-10 |  10:15:06.00 |  AA  |     1   |
    | 2018-10-10 |  16:57:01.14 |  BE  |     1   |

Требуемый выход

   Output

    |  Date      |    Time      | Name | accesses|  Failure |
    ---------------------------------------------------------
    | 2018-10-10 |  10:10:34.00 |  JA  |     1   |    1     |
    | 2018-10-10 |  10:14:10.10 |  AA  |     1   |    1     |
    | 2018-10-10 |  12:15:00.45 |  BE  |     1   |   NULL   |  
    | 2018-10-10 |  15:00:00.50 |  JA  |     1   |   NULL   |
    | 2018-10-10 |  16:56:56.15 |  BE  |     1   |    1     |

По существу, выход будет содержать обращения и сопоставлять таблицу сбоев с ближайшим временем, обнаруженным из таблицы обращений.Я пробовал разные алгоритмы сопоставления меток времени, но все равно получаю ошибки, так как не все доступы были неудачными, поэтому я хочу, чтобы в выводе было значение NULL.Спасибо

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Базы данных различаются по времени.Но общая идея заключается в том, что вы можете подойти к этому, используя exists:

select a.*,
       (case when exists (select 1
                          from failures f
                          where f.name = a.name and
                                f.date = a.date and
                                f.time > a.time - interval '1' minute and
                                f.time < a.time + interval '1' minute 
             then 1 else 0
        end) as failure_flag
from accesses a;

. При этом используется флаг со значениями 0 и 1.Очевидно, что вы можете удалить предложение else 0, чтобы получить NULL вместо 0.

Это на самом деле будет работать более точно, если объединить дату и время.Возможно, не стоит добавлять исправление для полуночи, в зависимости от характера ваших данных.

0 голосов
/ 07 июня 2018

По комментариям кажется, что это условие соединения будет работать

select distinct
    a.*
    ,Failure = case when f.Name is not null then 1 else null end
from Accesses a
left join Failure F on 
    f.Name = a.Name 
    and f.Time > dateadd(minute,-1, a.Time)
    and f.Time < dateadd(minute, 1, a.Time)
    and f.Date = a.Date 

Вот способ перестроить полночь, сделав DATETIME из ваших отдельных столбцов.Обратите внимание, что я добавил дополнительную строку в каждую таблицу.

declare @Accesses table (Date date, Time time, Name char(2), accesses bit)
insert into @Accesses
values
('2018-10-10','10:10:34.00','JA',1 ),
('2018-10-10','10:14:10.10','AA',1),
('2018-10-10','12:15:00.45','BE',1),
('2018-10-10','15:00:00.50','JA',1),
('2018-10-10','16:56:56.15','BE',1),
('2018-10-10','23:59:56.15','XX',1)

declare @Failure table (Date date, Time time, Name char(2), failure bit)
insert into @Failure
values
('2018-10-10','10:10:40.00','JA',1), 
('2018-10-10','10:15:06.00','AA',1),
('2018-10-10','16:57:01.14','BE',1),
('2018-10-11','00:00:01.15','XX',1)



select distinct
    a.*
    ,Failure = case when f.Name is not null then 1 else null end
from @Accesses a
left join @Failure F on 
    f.Name = a.Name 
    and cast(convert(varchar,f.date) + ' ' + left(convert(varchar,f.time),8) as datetime) > dateadd(minute,-1,cast(convert(varchar,a.date) + ' ' + left(convert(varchar,a.time),8) as datetime))
    and cast(convert(varchar,f.date) + ' ' + left(convert(varchar,f.time),8) as datetime) < dateadd(minute,1,cast(convert(varchar,a.date) + ' ' + left(convert(varchar,a.time),8) as datetime))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...