SQL Server:具有不同条款的CASE

目录

背景

CASE类型

简单CASE

搜索CASE

使用变量

使用Switch开关

多重比较

使用SELECT语句

使用Switch开关

多重比较

使用WHERE子句

CASE而不是OR

根据标志在条件之间切换

使用JOIN和ON子句

使用Update

使用ORDER BY

不同的列但相同的顺序

列明智顺序

其他

局限性

引用


背景

在这里,我们将检查CASE如何在任何允许有效表达式的语句或子句中使用的示例。例如,我们通常在一些语句中使用CASE,例如SELECTUPDATEDELETESETCASE也可以与JOINWHEREORDER BYHAVING子句一起使用。让我们检查一些示例。

CASE类型

CASE有两种类型:

  • 简单CASE:仅允许相等性检查
  • 搜索CASE:允许多次检查

简单CASE

CASE Expression
    WHEN Value1 THEN Result1
    WHEN Value2 THEN Result2
    …
    ELSE Result
END
DECLARE @userTypeId INT = 2;
DECLARE @userType VARCHAR(100);

/*Simple CASE*/   
SET @userType = CASE @userTypeId
                    WHEN 1 THEN 'Admin'
                    WHEN 2 THEN 'User'
                    ELSE 'Unknown'
                END;
SELECT @userType;

搜索CASE

CASE 
    WHEN BooleanExpression1 THEN Result1
    WHEN BooleanExpression2 THEN Result2
    …
    ELSE Result
END
DECLARE @userTypeId INT = 2;
DECLARE @userType VARCHAR(100);

/*Searched CASE*/   
SET @userType = CASE 
                    WHEN @userTypeId = 1 THEN 'Admin'
                    WHEN @userTypeId = 2 THEN 'User'
                    ELSE 'Unknown'
                END;
SELECT @userType; 

或者,我们也可以做:

DECLARE @inputNumber INT = 2
DECLARE @result NVARCHAR(MAX);
SELECT 
    @result =    
    CASE 
        WHEN ISNUMERIC(@inputNumber) = 1 AND @inputNumber % 2 = 0  THEN 'Even'
        WHEN ISNUMERIC(@inputNumber) = 1 AND @inputNumber % 2 = 1  THEN 'Odd'
        ELSE 'Not Number'
    END;
SELECT @result AS Result;

使用变量

使用Switch开关

DECLARE @userTypeId INT = 2;    /*set any number*/
DECLARE @userType VARCHAR(100);

SET @userType = CASE @userTypeId
                    WHEN 1 THEN 'Admin'
                    WHEN 2 THEN 'User'
                    ELSE 'Unknown'
                END;
SELECT @userType;

多重比较

DECLARE @inputNumber INT = 2
DECLARE @result NVARCHAR(MAX);
SELECT 
    @result =    
    CASE 
        WHEN ISNUMERIC(@inputNumber) = 1 AND @inputNumber % 2 = 0  THEN 'Even'
        WHEN ISNUMERIC(@inputNumber) = 1 AND @inputNumber % 2 = 1  THEN 'Odd'
        ELSE 'Not Number'
    END;
SELECT @result AS Result;

使用SELECT语句

使用Switch开关

/*use like switch*/
SELECT 
    Id, 
    CASE Id
        WHEN 1 THEN 'Admin'
        WHEN 2 THEN 'User'
        ELSE 'Anonymous'
    END
FROM (
    VALUES (1), (2), (NULL)
) AS Roles(Id) 

多重比较

/*multiple compare*/
SELECT 
    NumberValue,
    CASE 
        WHEN ISNUMERIC(NumberValue) = 1 AND NumberValue % 2 = 0  THEN 'Even'
        WHEN ISNUMERIC(NumberValue) = 1 AND NumberValue % 2 = 1  THEN 'Odd'
        ELSE 'Not Number'
    END
FROM(
    VALUES ('1'), ('2'), ('A'), (NULL)
) AS NumberList(NumberValue)

使用WHERE子句

以下是我们的表格和数据:

/*with where*/
DECLARE @tblUserPoints TABLE
(
    Name VARCHAR(100),
    UserType VARCHAR(100),
    Points INT
);
INSERT
INTO @tblUserPoints
VALUES 
('Dan', 'Sa', 90000),        /*will be selected*/
('Dan1', 'Sa', 80000),
('Ben', 'Admin', 70000),     /*will be selected*/
('Ben1', 'Admin', 60000),
('Kim', 'User', 50000),      /*will be selected*/
('Kim1', 'User', 40000); 

CASE而不是OR

下面是常规条件WHERE查询的示例:

/*regular 'OR' condition*/
SELECT *
FROM @tblUserPoints
WHERE (UserType = 'Sa' AND Points > 80000)
OR (UserType = 'Admin' AND Points > 60000)
OR (UserType = 'User' AND Points > 40000)

使用以下CASE方法重写上述查询:

/*using 'CASE' instated of 'OR'*/
SELECT *
FROM @tblUserPoints
WHERE (
    CASE 
        WHEN UserType = 'Sa' AND Points > 80000 THEN 1
        WHEN UserType = 'Admin' AND Points > 60000 THEN 1
        WHEN UserType = 'User' AND Points > 40000 THEN 1
        ELSE NULL
    END
) IS NOT NULL

和我们处理AND条件的方法一样。

根据标志在条件之间切换

在这里,取决于@flag,我们实际上是在WHERE条件之间切换的值:

/*switch between conditions depending on a flag*/
DECLARE @flag VARCHAR(50);
--SET @flag = 'Best';
--SET @flag = 'Better';
SET @flag = 'Good';

SELECT *
FROM @tblUserPoints
WHERE (
    CASE 
        WHEN @flag = 'Best' AND Points >= 80000 THEN 1
        WHEN @flag = 'Better' AND Points >= 60000 AND Points < 80000 THEN 1
        WHEN @flag = 'Good' AND Points >= 40000 AND Points < 60000 THEN 1
        ELSE NULL
    END
) IS NOT NULL 

使用JOINON子句

我们的表格和数据:

/*data*/
DECLARE @tblReputationTotal TABLE
(
    TotalPoint INT NULL,                
    Reputation VARCHAR(100)
);
DECLARE @tblReputation TABLE
(
    Point INT NULL,             /*sa*/
    RankPosition INT NULL,      /*admin*/
    Rating INT NULL,            /*user*/
    Reputation VARCHAR(100)
);
DECLARE @tblUserPoint TABLE
(
    Name VARCHAR(100),
    UserType VARCHAR(100),
    Point INT NULL,
    RankPosition INT NULL,
    Rating INT NULL
);
INSERT 
INTO @tblReputationTotal (TotalPoint, Reputation)
VALUES
(90000, 'Best'),
(70000, 'Better'),
(50000, 'Good');
INSERT 
INTO @tblReputation (Point, RankPosition, Rating, Reputation)
VALUES
(90000, NULL, NULL, 'Good Sa'),
(NULL, 70000, NULL, 'Good Admin'),
(NULL, NULL, 50000, 'Good User');
INSERT
INTO @tblUserPoint (Name, UserType, Point, RankPosition, Rating)
VALUES 
('Dan', 'Sa', 90000, NULL, NULL),       /*will be selected, Point*/
('Dan1', 'Sa', 80000, NULL, NULL),
('Ben', 'Admin', NULL, 70000, NULL),    /*will be selected, RankPosition*/
('Ben1', 'Admin', NULL, 60000, NULL),
('Kim', 'User', NULL, NULL, 50000),     /*will be selected, Rating*/
('Kim1', 'User', NULL, NULL, 40000); 

在这里,根据UserType列值,我们选择join列:

/*query*/
SELECT u.*, r.Reputation
FROM @tblUserPoint AS u
JOIN @tblReputation AS r
ON CASE
        WHEN u.UserType = 'Sa' AND u.Point = r.Point THEN 1
        WHEN u.UserType = 'Admin' AND u.RankPosition = r.RankPosition THEN 1
        WHEN u.UserType = 'User' AND u.Rating = r.Rating THEN 1
        ELSE 0
    END = 1;

或者,我们也可以做:

/*query*/
SELECT u.*, r.Reputation
FROM @tblReputationTotal AS r
JOIN @tblUserPoint AS u
ON r.TotalPoint =
    CASE
        WHEN u.UserType = 'Sa' THEN u.Point
        WHEN u.UserType = 'Admin' THEN u.RankPosition
        WHEN u.UserType = 'User' THEN u.Rating
        ELSE 0    /*can remove ELSE or set to -1. Don't set it to NULL*/
    END 

使用Update

DECLARE @tblBalance TABLE (Amount INT NULL, NumberType VARCHAR(100) NULL);
INSERT INTO @tblBalance(Amount) VALUES (1), (2), (3), (4), (NULL);

/*update*/
UPDATE @tblBalance
SET NumberType =    CASE 
                        WHEN Amount % 2 = 1 THEN 'Odd'
                        WHEN Amount % 2 = 0 THEN 'Even'
                        ELSE 'Null Value'
                    END;

SELECT * FROM @tblBalance; 

使用ORDER BY

我们的表格和数据:

/*data*/
DECLARE @tblEmployee TABLE
(
    Id INT,
    UserName VARCHAR(100),
    Email VARCHAR(100)
);
INSERT 
INTO @tblEmployee (Id, UserName, Email)
VALUES
(1, 'Dan', 'Dan@gmail.com'),
(2, 'Hen', 'Han@gmail.com'),
(3, 'Ben', 'Ben@gmail.com');


DECLARE @orderFilter VARCHAR(100);
SET @orderFilter = 'LoginName';
--SET @orderFilter = 'Email';

为了管理order,我们使用order指示器标志@orderFilter

@orderFilter将保存用于对特定数据集进行排序的预期列名或逻辑。

不同的列但相同的顺序

在这里,我们在UserNameEmailNone('')列之间切换,但使用相同的顺序DESC

SELECT *
FROM @tblEmployee
ORDER BY 
(
    CASE @orderFilter
        WHEN 'LoginName' THEN UserName
        WHEN 'Email' THEN Email
        ELSE ''                                /*need varchar, type as username 
                                                 and email are varchar*/
    END
) DESC,                                        /*can do individual column wise, 
                                                 check next query*/ 
Id ASC 

列明智顺序

它与前面的示例略有不同。在这里,order类型可以特定于每一列。

SELECT *
FROM @tblEmployee
ORDER BY 
CASE WHEN @orderFilter = 'LoginName' THEN UserName END DESC,
CASE WHEN @orderFilter = 'Email' THEN Email END ASC,
Id ASC 

将按顺序,UserName将按DESC排序, Email将按ASC排序,这取决于列选择标志@orderFilter的值。

其他

局限性

  • 在布尔表达式中不支持OR,而是使用IN()代替OR
  • 避免嵌套CASE,SQL Server只允许10个级别的CASE嵌套表达式。而是使用更多WHEN

引用

https://www.codeproject.com/Tips/1276985/SQL-Server-CASE-with-Different-Clause

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值