SQL-Server-2017: самостоятельное присоединение к таблице с использованием критериев отметки времени - PullRequest
0 голосов
/ 13 марта 2019

У меня есть таблица с именем events и выглядит так:

            timestamp      | intvalue | hostname | attributes
    2019-03-13 14:43:05.437|    257   |  room04  | Success 000
    2019-03-13 14:43:05.317|    257   |  room03  | Success 000
    2019-03-13 14:43:03.450|   2049   |  room05  | Error 108
    2019-03-13 14:43:03.393|     0    |  room05  | TicketNumber=3
    2019-03-13 14:43:02.347|     0    |  room04  | TicketNumber=2
    2019-03-13 14:43:02.257|     0    |  room03  | TicketNumber=1

Выше приведен пример таблицы, содержащей тысячи строк, подобных этой. Я объясню в нескольких словах, что вы видите в этой таблице. Столбец timestamp содержит дату и время, когда произошло каждое событие. В столбце intvalue 257 означает успешную запись, 2049 означает ошибку, а 0 означает, что заявка была сделана. hostname дает имя считывателя карт / билетов, который читает каждый билет, а столбец attributes дает некоторые подробности, такие как номер билета (1, 2, 3 и т. Д.) Или тип ошибки (т.е. 108 или 109 ) и если событие прошло успешно.

В этой ситуации есть шаблон, который говорит, что, если заявка запрашивает вход, и она действительна и произошла в то время, как 14:43:02.257, то сообщение об успешной записи будет записано в базу данных (как новый событие) через 6 секунд не более (что означает максимум 14: 49: 02.257) после того, как билет был прочитан читателем.

Если билет не может быть введен, то через 100 мсек сообщение об ошибке будет записано в базу данных.

Итак, в этом примере я хочу создать таблицу, подобную приведенной ниже

        timestamp      | intvalue | hostname |   result    |  ticketnumber
2019-03-13 14:43:05.437|    257   |  room04  | Success 000 | TicketNumber=2
2019-03-13 14:43:05.317|    257   |  room03  | Success 000 | TicketNumber=1
2019-03-13 14:43:03.450|   2049   |  room05  |  Error 108  | TicketNumber=3

Как вы можете видеть, билет с TicketNumber=3 сопоставляется с результатом Error 108, потому что если вы посмотрите на исходную таблицу, у них будет запас времени менее 100 мс, остальные два билета будут сопоставлены 1-к-1 1 с их соответствующими результатами, потому что запас по времени составляет менее 6 секунд (и более 100 мс). Вы также можете заметить, что имена хостов могут помочь сопоставлению, строка с атрибутом TicketNumber=3 имеет hostname из room05, как и следующая строка с атрибутом Error 108.

Я пытался самостоятельно присоединиться к этой таблице или присоединиться к ней с помощью CTE. Я использовал перекрестное применение, и я также попробовал методы, использующие datediff, но я потерпел неудачу и застрял. Есть ли кто-нибудь, кто может помочь мне и показать мне правильный путь достижения желаемого результата? Большое спасибо за ваше время.

Ответы [ 3 ]

1 голос
/ 14 марта 2019

Поскольку вы используете SQL 2017, вы можете использовать опережение / отставание.

with evt(timestamp,intvalue,hostname,attributes) as 
(

    select cast('2019-03-13 14:43:05.437' as datetime),   257 , 'room04','Success 000' union all
    select cast('2019-03-13 14:43:05.317' as datetime),   257 , 'room03','Success 000' union all
    select cast('2019-03-13 14:43:03.450' as datetime),  2049 , 'room05','Error 108' union all
    select cast('2019-03-13 14:43:03.393' as datetime),    0  , 'room05','TicketNumber=3' union all
    select cast('2019-03-13 14:43:02.347' as datetime),    0  , 'room04','TicketNumber=2' union all
    select cast('2019-03-13 14:43:02.257' as datetime),    0  , 'room03','TicketNumber=1'
    )
select [timestamp], intvalue, hostname, attributes, lag(attributes) over (partition by hostname order by timestamp) ticketnumber, datediff(ss,lag([timestamp]) over (partition by hostname order by timestamp), [timestamp]) lapse
from evt
order by timestamp
1 голос
/ 14 марта 2019

По-видимому, временные лаги не имеют большого значения, если только одна комната не может чередоваться с сообщениями об успехах и неудачах. Предполагая, что два запроса не происходят подряд без промежуточного события, вы можете использовать lag():

select e.*
from (select timestamp, intvalue, hostname, attributes,
             lag(attributes) over (partition by hostname order by timestamp) as ticketnumber
      from event
     ) e
where intvalue > 0
order by timestamp
1 голос
/ 14 марта 2019

ОК ... вот результат, который вы запрашивали на основе предоставленных вами данных.Это всего лишь пример того, как написать самостоятельное соединение, чтобы получить результаты в вашем примере.Я надеюсь, что это подтолкнет вас в правильном направлении.

IF OBJECT_ID('tempdb..#t') IS NOT NULL
BEGIN
    DROP TABLE #t
END
CREATE TABLE #t
(
    [timestamp] DATETIME,
    intValue INT,
    hostName VARCHAR(50),
    attributes VARCHAR(50)
)
INSERT INTO #t([timestamp], intValue, hostName, attributes)
VALUES  ('2019-03-13 14:43:05.437', 257, 'room04', 'Success 000'),
        ('2019-03-13 14:43:05.317',257, 'room03','Success 000'),
        ('2019-03-13 14:43:03.450',2049, 'room05','Error 108'),
        ('2019-03-13 14:43:03.393',0, 'room05','TicketNumber=3'),
        ('2019-03-13 14:43:02.347',0, 'room04','TicketNumber=2'),
        ('2019-03-13 14:43:02.257',0, 'room03','TicketNumber=1')

SELECT x.[timestamp], x.intValue, x.hostName, x.attributes result, y.attributes 
ticketnumber
FROM (SELECT * FROM #t WHERE intValue > 0) AS x 
INNER JOIN #t y
ON x.hostName = y.hostName AND y.intValue = 0
GROUP BY x.[timestamp], x.intValue, x.hostName, x.attributes, y.attributes
ORDER BY x.[timestamp] DESC

Я бы не стал копировать это в ваш проект и использовать его, это всего лишь пример того, как использовать объединение.Мне понадобится гораздо больше информации о том, чего вы хотите достичь, прежде чем публиковать полноценное решение, так как есть гораздо более совершенные способы создания отчетов для больших наборов данных.- Билл

...