SQL select跨3个表重用subselect

时间:2018-08-07 11:52:40

标签: sql-server tsql select

我需要从WatchDog表中获取一些行。 简化的表脚本如下

Use Question
GO

CREATE TABLE [dbo].[Errors](
    [Id] [int] NOT NULL,
    [WatchDogId] [int] NOT NULL,
    [ErrName] [nvarchar](max) NOT NULL,
    [TimeStamp] [datetimeoffset](7) NOT NULL
)
GO

CREATE TABLE [dbo].[StopperCode](
    [Id] [int] NOT NULL,
    [ErrorCode] [nvarchar](max) NOT NULL
)
GO

CREATE TABLE [dbo].[Watchdog](
    [Id] [int] NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [ErrFlag] [bit] NOT NULL,
)
GO

INSERT [dbo].[StopperCode] ([Id], [ErrorCode]) VALUES (1, N'Stop1')
INSERT [dbo].[StopperCode] ([Id], [ErrorCode]) VALUES (2, N'Stop2')
INSERT [dbo].[Watchdog] ([Id], [Name], [ErrFlag]) VALUES (1, N'Dog1', 0)
INSERT [dbo].[Watchdog] ([Id], [Name], [ErrFlag]) VALUES (2, N'Dog2', 1)
INSERT [dbo].[Watchdog] ([Id], [Name], [ErrFlag]) VALUES (3, N'Dog3', 1)
INSERT [dbo].[Errors] ([Id], [WatchDogId], [ErrName], [TimeStamp]) VALUES (1, 2, N'Stop1 because blabla', CAST(N'2018-08-07T12:18:02.9939600+02:00' AS DateTimeOffset))
INSERT [dbo].[Errors] ([Id], [WatchDogId], [ErrName], [TimeStamp]) VALUES (2, 2, N'ErrSmall', CAST(N'2018-08-07T12:20:21.3287921+02:00' AS DateTimeOffset))
INSERT [dbo].[Errors] ([Id], [WatchDogId], [ErrName], [TimeStamp]) VALUES (3, 2, N'Stop2 bla bla', CAST(N'2018-08-07T12:20:39.3095900+02:00' AS DateTimeOffset))
INSERT [dbo].[Errors] ([Id], [WatchDogId], [ErrName], [TimeStamp]) VALUES (4, 3, N'Stop1 bla bla', CAST(N'2018-08-07T12:20:59.2625851+02:00' AS DateTimeOffset))
INSERT [dbo].[Errors] ([Id], [WatchDogId], [ErrName], [TimeStamp]) VALUES (5, 3, N'ErrSmall', CAST(N'2018-08-07T12:21:57.6044187+02:00' AS DateTimeOffset))
GO

我需要从使用日期时间过滤的WatchDog中获取失败的任务(仅返回在过去一小时内失败的任务返回不超过2次的任务),并且最后一个错误不在StopperCode表中。停止程序代码仅包含错误消息的开头。

我想基于对此样本集执行的查询中的条件获取Errors.Id = 3。因为上一个错误在StopperCode表中,所以不应返回2。如果最近一个小时内WatchDogId = 3发生了2个以上(不是来自StopperCode的)错误,则也不应该返回该错误。 现在,我可以编写带有子选择的尴尬选择,但是我想以某种方式更有效地执行此操作。而且我也不想重复两次相同的选择。

1 个答案:

答案 0 :(得分:1)

如果我的理解正确,那么以下查询将为您服务。

;WITH CTE AS(
SELECT ROW_NUMBER() OVER(PARTITION BY WatchDogId ORDER BY ID DESC) AS RNO
,*
FROM [#Errors] E
)
SELECT C.ErrName, C.WatchDogId, W.Name
FROM CTE C
INNER JOIN [#Watchdog] W ON C.WatchDogId = W.Id
LEFT JOIN [#StopperCode] S ON C.ErrName LIKE S.ErrorCode+'%'
WHERE C.RNO=1
AND S.Id IS NULL

由于我没有得到您最后1小时的病情,我把它留给了您。

结果:

ErrName   WatchDogId    Name
ErrSmall  3             Dog3