Сопоставить данные двух строк с разной отметкой времени в одной строке (SQL Server) - PullRequest
0 голосов
/ 07 сентября 2018

У меня проблема с запросом к SQL Server.

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

Есть также несколько строк, которые содержат в качестве атрибута строку типа Eticket result. Это событие генерируется, когда билет недействителен, и система показывает причину недействительности билета.

enter image description here

То, что я хочу сделать, - это создать новый столбец (названный как «причина»), который будет содержать все атрибуты, похожие на «Результат Eticket». Дело в том, что все эти атрибуты, содержащие результат ETICKET, должны соответствовать правильному номеру заявки. Разница во времени между атрибутом причины и временной меткой недействительного билета никогда не превышает 500 миллисекунд.

Чтобы сделать его более понятным, я даю вам еще один скриншот ниже того, что я хочу сделать.

enter image description here

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

DECLARE @alarm_table TABLE (
 /*1*/server_timestamp     DATETIME ,
 /*2*/museum                 VARCHAR(255),
 /*3*/turnstile          VARCHAR(255),
 /*4*/entrance            VARCHAR(255),
 /*5*/cardnumber          VARCHAR(255),
 /*6*/result              VARCHAR(255),
 /*7*/reason              VARCHAR(255),
 /*8*/attributes             VARCHAR(255)

);

INSERT INTO @alarm_table
SELECT
  /*1*/servertimestamp,
  /*2*/hostname,
  /*3*/substring([hostname], PatIndex('%[0-9]%', [hostname]), len([hostname])),
  /*4*/substring(attributes, 31, 39),
  /*5*/attributes,
  /*6*/'NOT OK',
  /*7*/'',
  /*8*/attributes--substring(attributes, 70, 30)
FROM
  eventlog el
where
 (el.servertimestamp  BETWEEN '8/24/2018' AND DATEADD(dd, +1, '8/27/2019'))
 and (attributes like '%ticket %' and attributes like '%eticketing%' )
 and hostname <> 'tapaeos'
order by
  el.timestamp

 UPDATE @alarm_table
  SET cardnumber = substring(attributes, 31, 39)


  UPDATE @alarm_table
  SET result =  case
                   when 
                        (attributes like '%ticket 8%'
                        or attributes like '%ticket 9%'
                        or attributes like '%ticket 10%'
                        or attributes like '%ticket 11%' 
                        or attributes like '%ticket 12%' 
                        or attributes like '%ticket 13%' 
                        or attributes like '%ticket 14%' 
                        or attributes like '%knossos ticket 5%'
                        or attributes like '%knossos ticket 6%'
                        or attributes like '%knossos ticket 7%'
                        or attributes like '%klitys ticket 5%'
                        or attributes like '%klitys ticket 6%'
                        or attributes like '%klitys ticket 7%'
                        or attributes like '%olympieio ticket 5%'
                        or attributes like '%olympieio ticket 6%'
                        or attributes like '%olympieio ticket 7%'
                        ) 
                    then 'NOT OK'
                   else 'OK'
              end

  UPDATE @alarm_table
    SET reason = case
                    when result = 'NOT OK' then 
                    (SELECT top 1 attributes 
                     FROM eventlog 
                     WHERE DATEDIFF(second,servertimestamp,server_timestamp)<=1)
                   else ' '
              end

  UPDATE @alarm_table
    SET museum  = case
                 when museum like '%olymp%' then 'Olympieio'
                 when museum like '%knoss%' then 'Knossos'
                 when museum like '%sslope%' then 'Klitys'
                 when museum like '%acrop%' then 'Acropolis'
                end

  select
  server_timestamp,
  museum,
  turnstile,
  cardnumber,
  result,
  reason
 -- attributes
from
  @alarm_table



  order by server_timestamp desc  

Ваша помощь будет высоко ценится, спасибо за ваше время.

1 Ответ

0 голосов
/ 07 сентября 2018

Попробуйте это:

select e1.*, e2.attributes reason
from (
    select *
    from eventlog
    where charindex('ETICKET Result', attributes) = 0
) e1 left join (
    select timestamp, attributes
    from eventlog
    where charindex('ETICKET Result', attributes) > 0
) e2 on abs(datediff(millisecond, e1.timestamp, e2.timestamp)) <= 500

В e1 мы запрашиваем все записи, которые являются правильными (без ETICKET Reason), в e2 мы выбираем все неправильные записи. Затем мы объединяем оба результата по разнице во времени в миллисекундах.

...