使用单个 Case When 逻辑更新多列 - SQL 服务器
Update more than one column with single Case When logic - SQL Server
我需要创建以下 XML 自定义元素和使用硬编码数据的属性。
Table 架构:StudentMark:
CREATE TABLE [dbo].[StudentMark]
(
[StudentMarkId] int IDENTITY(1,1) NOT NULL,
[StudentId] uniqueidentifier NOT NULL,
[SubjectId] uniqueidentifier NOT NULL,
[Score] int NOT NULL,
[GeneratedOn] datetime2(2) NOT NULL,
[IsPass] bit NULL,
[Result] varchar(100) NULL,
CONSTRAINT [PK_StudentMark]
PRIMARY KEY CLUSTERED ([StudentMarkId] ASC)
) ON [PRIMARY]
样本种子数据
INSERT INTO [dbo].[StudentMark] ([StudentId], [SubjectId], [GeneratedOn], [Score])
VALUES ('FC3CB475-B480-4129-9190-6DE880E2D581', '0D72F79E-FB48-4D3E-9906-B78A9D105081', '2017-08-10 10:10:15', 95),
('0F4EF48C-93E3-41AA-8295-F6B0E8D8C3A2', '0D72F79E-FB48-4D3E-9906-B78A9D105081', '2017-08-10 10:10:15', 60),
('0F4EF48C-93E3-41AA-8295-F6B0E8D8C3A2', 'AB172272-D2E9-49E1-8040-6117BB6743DB', '2017-08-16 09:06:20', 25),
('FC3CB475-B480-4129-9190-6DE880E2D581', 'AB172272-D2E9-49E1-8040-6117BB6743DB', '2017-08-16 09:06:20', 45);
要求:我需要根据单一逻辑更新几列[IsPass]
和[Result]
。
查询 #1:
UPDATE SM
SET SM.[Result] = CASE WHEN SM.[Score] >= 75 THEN N'OUTSTANDING'
WHEN SM.[Score] >= 60 AND [Score] < 75 THEN N'VERY GOOD'
WHEN SM.[Score] >= 50 AND [Score] < 60 THEN N'GOOD'
WHEN SM.[Score] >= 40 AND [Score] < 50 THEN N'AVERAGE'
ELSE N'FAIL' END
FROM [dbo].[StudentMark] SM
查询 #2:
UPDATE SM
SET SM.[IsPass] = CASE WHEN SM.[Result] = N'FAIL' THEN 0 ELSE 1 END
FROM [dbo].[StudentMark] SM
How could I merge these two query in a single UPDATE
Query without
replicating the CASE WHEN
.
请帮助我。
UPDATE SM
SET SM.[Result] = CASE WHEN SM.[Score] >= 75 THEN N'OUTSTANDING'
WHEN SM.[Score] >= 60 AND [Score] < 75 THEN N'VERY GOOD'
WHEN SM.[Score] >= 50 AND [Score] < 60 THEN N'GOOD'
WHEN SM.[Score] >= 40 AND [Score] < 50 THEN N'AVERAGE'
ELSE N'FAIL' END, SM.[IsPass] = CASE WHEN SM.[Score] < 40 THEN 0 ELSE 1 END
FROM [dbo].[StudentMark] SM
您可以通过添加 ,(comma)
轻松做到这一点
像这样:
WITH DataSource ([StudentMarkId], [Result]) AS
(
SELECT [StudentMarkId]
,CASE WHEN SM.[Score] >= 75 THEN N'OUTSTANDING'
WHEN SM.[Score] >= 60 AND [Score] < 75 THEN N'VERY GOOD'
WHEN SM.[Score] >= 50 AND [Score] < 60 THEN N'GOOD'
WHEN SM.[Score] >= 40 AND [Score] < 50 THEN N'AVERAGE'
ELSE N'FAIL' END
FROM [dbo].[StudentMark]
)
UPDATE [dbo].[StudentMark]
SET SM.[Result] = DS.[Result]
,SM.[IsPass] = CASE WHEN DS.[Result] = N'FAIL' THEN 0 ELSE 1 END
FROM [dbo].[StudentMark] SM
INNER JOIN DataSource DS
ON SM.[StudentMarkId] = DS.[StudentMarkId];
您可以简单地重复逻辑:
UPDATE SM
SET SM.[Result] = (CASE WHEN SM.[Score] >= 75 THEN N'OUTSTANDING'
WHEN SM.[Score] >= 60 THEN N'VERY GOOD'
WHEN SM.[Score] >= 50 THEN N'GOOD'
WHEN SM.[Score] >= 40 THEN N'AVERAGE'
ELSE N'FAIL'
END),
SM.IsPass = (CASE WHEN SM.Score >= 40 THEN 1 ELSE 0 END)
FROM [dbo].[StudentMark] SM;
注意:CASE
表达式保证按顺序求值,因此每行只需要比较一次。
不过,我要指出的是,一个更好的选择可能是放弃 IsPass
作为 table 中的一列,并使其成为一个计算列:
alter table [dbo].[StudentMark]
add IsPass as (CASE WHEN Result <> N'FAIL' THEN 1 ELSE 0 END);
这样可以确保值始终正确。事实上,您可以对 Result
执行相同的操作,因此两者都会被计算出来。
我需要创建以下 XML 自定义元素和使用硬编码数据的属性。
Table 架构:StudentMark:
CREATE TABLE [dbo].[StudentMark]
(
[StudentMarkId] int IDENTITY(1,1) NOT NULL,
[StudentId] uniqueidentifier NOT NULL,
[SubjectId] uniqueidentifier NOT NULL,
[Score] int NOT NULL,
[GeneratedOn] datetime2(2) NOT NULL,
[IsPass] bit NULL,
[Result] varchar(100) NULL,
CONSTRAINT [PK_StudentMark]
PRIMARY KEY CLUSTERED ([StudentMarkId] ASC)
) ON [PRIMARY]
样本种子数据
INSERT INTO [dbo].[StudentMark] ([StudentId], [SubjectId], [GeneratedOn], [Score])
VALUES ('FC3CB475-B480-4129-9190-6DE880E2D581', '0D72F79E-FB48-4D3E-9906-B78A9D105081', '2017-08-10 10:10:15', 95),
('0F4EF48C-93E3-41AA-8295-F6B0E8D8C3A2', '0D72F79E-FB48-4D3E-9906-B78A9D105081', '2017-08-10 10:10:15', 60),
('0F4EF48C-93E3-41AA-8295-F6B0E8D8C3A2', 'AB172272-D2E9-49E1-8040-6117BB6743DB', '2017-08-16 09:06:20', 25),
('FC3CB475-B480-4129-9190-6DE880E2D581', 'AB172272-D2E9-49E1-8040-6117BB6743DB', '2017-08-16 09:06:20', 45);
要求:我需要根据单一逻辑更新几列[IsPass]
和[Result]
。
查询 #1:
UPDATE SM
SET SM.[Result] = CASE WHEN SM.[Score] >= 75 THEN N'OUTSTANDING'
WHEN SM.[Score] >= 60 AND [Score] < 75 THEN N'VERY GOOD'
WHEN SM.[Score] >= 50 AND [Score] < 60 THEN N'GOOD'
WHEN SM.[Score] >= 40 AND [Score] < 50 THEN N'AVERAGE'
ELSE N'FAIL' END
FROM [dbo].[StudentMark] SM
查询 #2:
UPDATE SM
SET SM.[IsPass] = CASE WHEN SM.[Result] = N'FAIL' THEN 0 ELSE 1 END
FROM [dbo].[StudentMark] SM
How could I merge these two query in a single
UPDATE
Query without replicating theCASE WHEN
.
请帮助我。
UPDATE SM
SET SM.[Result] = CASE WHEN SM.[Score] >= 75 THEN N'OUTSTANDING'
WHEN SM.[Score] >= 60 AND [Score] < 75 THEN N'VERY GOOD'
WHEN SM.[Score] >= 50 AND [Score] < 60 THEN N'GOOD'
WHEN SM.[Score] >= 40 AND [Score] < 50 THEN N'AVERAGE'
ELSE N'FAIL' END, SM.[IsPass] = CASE WHEN SM.[Score] < 40 THEN 0 ELSE 1 END
FROM [dbo].[StudentMark] SM
您可以通过添加 ,(comma)
像这样:
WITH DataSource ([StudentMarkId], [Result]) AS
(
SELECT [StudentMarkId]
,CASE WHEN SM.[Score] >= 75 THEN N'OUTSTANDING'
WHEN SM.[Score] >= 60 AND [Score] < 75 THEN N'VERY GOOD'
WHEN SM.[Score] >= 50 AND [Score] < 60 THEN N'GOOD'
WHEN SM.[Score] >= 40 AND [Score] < 50 THEN N'AVERAGE'
ELSE N'FAIL' END
FROM [dbo].[StudentMark]
)
UPDATE [dbo].[StudentMark]
SET SM.[Result] = DS.[Result]
,SM.[IsPass] = CASE WHEN DS.[Result] = N'FAIL' THEN 0 ELSE 1 END
FROM [dbo].[StudentMark] SM
INNER JOIN DataSource DS
ON SM.[StudentMarkId] = DS.[StudentMarkId];
您可以简单地重复逻辑:
UPDATE SM
SET SM.[Result] = (CASE WHEN SM.[Score] >= 75 THEN N'OUTSTANDING'
WHEN SM.[Score] >= 60 THEN N'VERY GOOD'
WHEN SM.[Score] >= 50 THEN N'GOOD'
WHEN SM.[Score] >= 40 THEN N'AVERAGE'
ELSE N'FAIL'
END),
SM.IsPass = (CASE WHEN SM.Score >= 40 THEN 1 ELSE 0 END)
FROM [dbo].[StudentMark] SM;
注意:CASE
表达式保证按顺序求值,因此每行只需要比较一次。
不过,我要指出的是,一个更好的选择可能是放弃 IsPass
作为 table 中的一列,并使其成为一个计算列:
alter table [dbo].[StudentMark]
add IsPass as (CASE WHEN Result <> N'FAIL' THEN 1 ELSE 0 END);
这样可以确保值始终正确。事实上,您可以对 Result
执行相同的操作,因此两者都会被计算出来。