我有一个名为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
匹配,因为如果您查看初始表,它们的时间裕度小于100ms,则其他两张票证将匹配一对一的结果,因为时间余量少于6秒(且超过100ms)。您还可以注意到,主机名可以帮助进行匹配,属性为TicketNumber=3
的行的hostname
为room05
,就像下一行属性为{ {1}}。
我一直试图自行加入该表或将其与CTE结合。我使用了交叉应用,也尝试过使用Error 108
的方法,但是我失败了,我陷入了困境。
有没有人可以帮助我并向我展示实现预期结果的正确方法?
非常感谢您的宝贵时间。
答案 0 :(得分:1)
确定...这是根据您提供的数据要求的结果。这只是如何编写自我联接以获取示例中结果的示例。我希望这能将您推向正确的方向。
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
我不会尝试将其复制到您的项目中并使用它,这只是如何使用联接的一个示例。在发布完整的解决方案之前,我将需要更多有关您要完成的工作的信息,因为还有很多更好的方法可以为大型数据集生成报告。 -比尔
答案 1 :(得分:1)
由于使用的是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
答案 2 :(得分:1)
时间延迟似乎并没有真正改变,除非以某种方式可以将单个房间与成功和失败消息交织在一起。假设在没有介入事件的情况下没有连续发生两个请求,那么可以使用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