如何从 SQL Server 存储过程中的 3 列中获取 MAX 值?
Posted
技术标签:
【中文标题】如何从 SQL Server 存储过程中的 3 列中获取 MAX 值?【英文标题】:How to get a MAX value from 3 columns in SQL Server stored procedures? 【发布时间】:2021-12-27 18:21:14 【问题描述】:我正在开发一个使用 C# 和 SQL Server 数据库的项目。现在我必须编写一个存储过程,它需要从 3 个不同的列中获取一个 MAX 值。
我的代码如下所示:
CREATE PROCEDURE [dbo].[sp_GetClass]
@surname nvarchar(50),
@maxClass int OUT
AS
SELECT @maxClass = MAX
FROM (VALUES (Programming), (Mathematics), (Physics))
FROM MissLess
WHERE Surname LIKE '%' + @surname + '%'
GO
我收到第二个FROM
的错误,我不知道如何解决它。
这个想法是让它在输入姓氏时从这些列中获取最大值。当没有输入时(按回车键),它只显示所有姓氏中这 3 列的最大值。
对不起,如果格式或问题没有被问到,这是我在这里的第一篇文章。
编辑:@name 出错,应该是@surname;并且名称应该是姓氏。 编辑最终版:感谢您的出色帮助。我是所有这一切的超级新手,但这一切似乎都很有趣。差点就放弃了,但决定试一试。谢谢大家的回答!!!
【问题讨论】:
旁注:您应该不为您的存储过程使用sp_
前缀。微软有reserved that prefix for its own use (see Naming Stored Procedures),你确实会在未来某个时候冒着名称冲突的风险。 It's also bad for your stored procedure performance。最好只是简单地避免 sp_
并使用其他东西作为前缀 - 或者根本不使用前缀!
感谢您提供的信息。我才刚开始,老师很可能会让我们知道这件事。感谢您的提醒。
或者,如果您使用的是 Azure SQL 数据库,请查看 GREATEST
函数
【参考方案1】:
您需要将所选行的这三个值放入存储过程中的表变量中,以便能够将MAX
应用于它们。
尝试这样的事情 - 我不知道这些值是什么 datatype - 只是假设 INT
在这里,根据需要进行调整:
CREATE PROCEDURE [dbo].[GetMaxValue]
@surname NVARCHAR(50),
@maxClass INT OUTPUT
AS
DECLARE @IntTbl TABLE (AValue INT);
INSERT INTO @IntTbl (AValue)
SELECT Programming
FROM MissLess
WHERE Name LIKE '%' + @name + '%'
UNION ALL
SELECT Mathematics
FROM MissLess
WHERE Name LIKE '%' + @name + '%'
UNION ALL
SELECT Physics
FROM MissLess
WHERE Name LIKE '%' + @name + '%';
SELECT @maxClass = MAX(AValue)
FROM @IntTbl;
GO
更新 - 好的,你要求它;-)
由于您的搜索条件可能匹配多行(至少您可能不能完全排除这种情况),您必须首先获取每列的 MAX()
,基于搜索条件:
CREATE PROCEDURE [dbo].[GetMaxValue]
@surname NVARCHAR(50),
@maxClass INT OUTPUT
AS
DECLARE @MaxMath INT, @MaxPhys INT, @MaxProgr INT;
SELECT
@MaxMath = MAX(Mathematics),
@MaxPhys = MAX(Physics),
@MaxProgr = MAX(Programming)
FROM
MissLess
WHERE
Name LIKE '%' + @name + '%';
IF @MaxMath > @MaxPhys
BEGIN
IF @MaxMath > @MaxProgr
-- @MaxMath is bigger than both @MaxPhys AND @MaxProgr --> it's the overall MAX()
SET @maxClass = @MaxMath;
ELSE
-- @MaxMath is bigger than @MaxPhys, but smaller than @MaxProgr
SET @maxClass = @MaxProgr;
END
ELSE BEGIN
IF @MaxPhys > @MaxProgr
-- @MaxPhys is bigger than both @MaxMath AND @MaxProgr --> it's the overall MAX()
SET @maxClass = @MaxPhys;
ELSE
-- @MaxPhys is bigger than @MaxMath, but smaller than @MaxProgr
SET @maxClass = @MaxProgr;
END;
SELECT @maxClass = MAX(AValue)
FROM @IntTbl;
GO
更新 #2:对于不使用表变量进行更新的更好、更简洁的解决方案 - 请参阅@AndrewCorrigan 的答案,使用CASE
表达式。
【讨论】:
不可能全部放在同一张表里吗?是的,所有这些数据类型值都是 INT 嵌套的 IF 语句会是什么样子? 这种更新是荒谬的——case 语句比 if 块简单得多。【参考方案2】:你可以做 (Fiddle)
SELECT MAX(s)
FROM MissLess
CROSS APPLY (VALUES (Programming), (Mathematics), (Physics)) V(s)
WHERE Name LIKE '%' + @name + '%'
如果@name
谓词匹配多行,您将无法指出它来自哪一行
【讨论】:
【参考方案3】:作为使用嵌套 CASE 语句的替代解决方案:
SELECT @maxClass = MAX(CASE
WHEN Programming >= Mathematics
AND Programming >= Physics
THEN Programming
WHEN Mathematics >= Physics
AND Mathematics >= Programming
THEN Mathematics
ELSE Physics
END)
FROM MissLess
WHERE Surname LIKE '%' + @surname + '%';
【讨论】:
同意 - 这是一个更好、更简洁的解决方案,无需使用表变量 - 干杯!以上是关于如何从 SQL Server 存储过程中的 3 列中获取 MAX 值?的主要内容,如果未能解决你的问题,请参考以下文章
我应该如何使用 sql server 中的存储过程将列名存储在变量中?
如何从 SQL Server Management Studio 中的表生成 CRUD 存储过程
将数据从 MS Sql Server 存储过程导出到 excel 文件