【问题标题】:SQL select accross 3 tables reusing subselect使用 subselect 跨 3 个表进行 SQL 选择
【发布时间】:2018-08-07 11:52:40
【问题描述】:

我需要从 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。 2 不应返回,因为最后一个错误在 StopperCode 表中。如果上一小时 WatchDogId=3 的错误超过 2 个(不是来自 StopperCode),则也不应该返回。 现在我可以用子选择写一些尴尬的选择,但我想以某种方式更有效地做到这一点。而且我也不想做同样的选择两次。

【问题讨论】:

  • 很高兴您将示例数据发布为 DDL+DML,但如果您还可以发布您想要的结果以及您迄今为止尝试过的内容,那就更好了。
  • 简要描述了所需的结果,因为无需准确指定我想要的结果。为了简单起见,WatchDogId 作为答案就足够了。乍一看,我尝试的内容非常不可读和浪费。所以我宁愿把它排除在外。

标签: sql-server tsql select


【解决方案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

【讨论】:

    猜你喜欢
    • 2011-03-29
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 2014-10-31
    相关资源
    最近更新 更多