我正在尝试获取 **TableB ** 中的最新记录以获得 ID .. 我厌倦了对最高值进行排名,然后使用结果将以下条件应用于 TableA 中名为“状态”的列:
如果 end 为 null 或空白,则 status = 'Currently Running'
如果最新记录来自过去 48 小时,则 status = 'Recently FInished'
如果结束时间超过 48 小时,则 status = 'not run in more than 48hours'
else '最近没有活动'
CREATE TABLE [dbo].[TableA](
[ID] [varchar](50) NULL,
[Status] [varchar](50) NULL
)
CREATE TABLE [dbo].[TableB](
[SiteId] [varchar](50) NULL,
[db_addr] [varchar](50) NULL,
[Start] [datetime] NULL,
[End] [datetime] NULL,
[ID] [varchar](50) NULL
)
GO
INSERT [dbo].[TableA] ([ID], [Status]) VALUES (N'Z1001', N'')
INSERT [dbo].[TableA] ([ID], [Status]) VALUES (N'Z1002', N'')
INSERT [dbo].[TableA] ([ID], [Status]) VALUES (N'Z1003', N'')
INSERT [dbo].[TableA] ([ID], [Status]) VALUES (N'Z3002', N'')
INSERT [dbo].[TableB] ([SiteId], [db_addr], [Start], [End], [ID]) VALUES (N'1001', N'E001', CAST(N'2023-05-01T00:00:00.000' AS DateTime), CAST(N'2023-05-02T00:10:00.000' AS DateTime), N'Z1001')
INSERT [dbo].[TableB] ([SiteId], [db_addr], [Start], [End], [ID]) VALUES (N'1001', N'E001', CAST(N'2023-05-02T01:00:00.000' AS DateTime), CAST(N'2023-05-02T01:10:00.000' AS DateTime), N'Z1001')
INSERT [dbo].[TableB] ([SiteId], [db_addr], [Start], [End], [ID]) VALUES (N'1001', N'E001', CAST(N'2023-05-03T01:00:00.000' AS DateTime), CAST(N'2023-05-03T01:10:00.000' AS DateTime), N'Z1001')
INSERT [dbo].[TableB] ([SiteId], [db_addr], [Start], [End], [ID]) VALUES (N'2001', N'B002', CAST(N'2023-05-01T00:00:00.000' AS DateTime), CAST(N'2023-05-02T00:10:00.000' AS DateTime), N'Z2001')
INSERT [dbo].[TableB] ([SiteId], [db_addr], [Start], [End], [ID]) VALUES (N'2001', N'B002', CAST(N'2023-05-02T01:00:00.000' AS DateTime), CAST(N'2023-05-02T01:10:00.000' AS DateTime), N'Z2001')
INSERT [dbo].[TableB] ([SiteId], [db_addr], [Start], [End], [ID]) VALUES (N'3001', N'B005', CAST(N'2023-05-02T01:00:00.000' AS DateTime), NULL, N'Z3001')
INSERT [dbo].[TableB] ([SiteId], [db_addr], [Start], [End], [ID]) VALUES (N'3002', N'C007', CAST(N'2023-05-10T01:00:00.000' AS DateTime), CAST(N'2023-05-10T01:00:00.000' AS DateTime), N'Z3002')
我试着写一个 SQL Partition 语句,然后是 CASE,但都出错了。
WITH cte AS (
SELECT a.ID, Status,
ROW_NUMBER() OVER (PARTITION BY b.db_addr, b.ID ORDER BY b.[End] DESC) AS rn,
MAX(b.[End]) OVER (PARTITION BY b.db_addr, b.ID) AS latest_end
FROM TableA a
JOIN TableB b ON a.ID = b.ID
)
UPDATE a
SET Status = CASE
WHEN cte.latest_end IS NULL OR cte.latest_end = '' THEN 'Currently Discharging'
WHEN cte.rn = 1 AND cte.latest_end >= DATEADD(hour, -48, GETDATE()) THEN 'Discharged recently'
ELSE 'Not discharged in more than 48hours'
END
FROM TableA a
LEFT JOIN cte ON a.ID = cte.ID
WHERE a.ID IS NOT NULL;
为每个ID检索最近的行,使用window方法
ROW_NUMBER()
,然后使用case
子句得到预期的结果:
with cte as (
select a.*, b.[End], ROW_NUMBER() OVER (partition by a.ID order by [End]) as rn
from TableA a
inner join TableB b on b.ID = a.ID
)
select ID, case when [End] is null then 'Currently Running'
when [End] >= DATEADD(day, -2, GETDATE()) then 'Recently FInished'
when [End] < DATEADD(day, -2, GETDATE()) then 'not run in more than 48hours'
else 'no recent activity' end as Status
from cte
where rn = 1
这是更新声明:
with cte as (
select a.*, b.[End], ROW_NUMBER() OVER (partition by a.ID order by [End]) as rn
from TableA a
inner join TableB b on b.ID = a.ID
)
UPDATE TableA
set TableA.Status = case when [End] is null then 'Currently Running'
when [End] >= DATEADD(day, -2, GETDATE()) then 'Recently FInished'
when [End] < DATEADD(day, -2, GETDATE()) then 'not run in more than 48hours'
else 'no recent activity' end
from cte c
inner join TableA a on a.ID = c.ID
where rn = 1
结果:
ID Status
Z1001 not run in more than 48hours
Z1002 not run in more than 48hours
Z3001 Currently Running
Z3002 Recently FInished
看起来你不需要窗户 在这里发挥作用。您可以从第二个表中获取每个
end
的最新id
,只需max
.
我们还可以避免 CTE(您的代码稍后会连接回表),并直接从相关子查询返回新值:
update a
set status = (
select
case
when max([End]) is null then 'currently running'
when max([End]) >= dateadd(day, -2, getdate()) then 'recently finished'
else 'did not run in more than 48 hours'
end
from tableb b
where b.id = a.id
)
from tablea a
where a.id is not null
备注:
case
的最后一个分支(产生最近没有活动的分支)无法访问;之前的分支,没有在超过 48 小时内运行,将首先匹配