存储数据范围的颜色并用于 SQL 服务器中的 case 语句

Store color for data ranges and use in case statement in SQL Server

我有如下数据集。 Fiddle URL

我需要使用上面 table 中的运算符获取给定数字的颜色 table。

例如;

当我调用函数getColor(6)时,应该return PURPLE.

当我调用函数getColor(0)时,应该return RED.

我怎样才能做到这一点?

最简单的解决方案是使用 CASE 表达式为每个运算符创建匹配条件:

DECLARE @val NUMERIC(10) = 6;

SELECT /* TOP 1 */ *
FROM #range_color
CROSS APPLY (SELECT @val - range_number) AS ca(diff)
WHERE CASE WHEN diff <  0 AND range_operator = '<'  THEN 1 END = 1
OR    CASE WHEN diff <= 0 AND range_operator = '<=' THEN 1 END = 1
OR    CASE WHEN diff >= 0 AND range_operator = '>=' THEN 1 END = 1
OR    CASE WHEN diff >  0 AND range_operator = '>'  THEN 1 END = 1
ORDER BY ABS(diff)

你能试试下面的查询吗

CREATE FUNCTION getColor
(@Colorcode decimal(18,2))
RETURNS  VARCHAR(10)
AS
BEGIN
DECLARE @color VARCHAR(10)='RED'
SELECT TOP (1) @color=range_color FROM range_color 
WHERE range_number between range_number AND @Colorcode - (CASE WHEN 
@Colorcode=0 THEN 1 ELSE 0 END) Order by range_number desc
RETURN @color
END 

我试过另一个查询,

DECLARE @val DECIMAL(18,2)=1

DECLARE @temp TABLE(color VARCHAR(10),flag BIT,range_number NUMERIC(10),diff int)
DECLARE @temp1 TABLE(color VARCHAR(10),range_number NUMERIC(10),Operator VARCHAR(10),range_color_id INT)
INSERT INTO @temp1
SELECT range_color,range_number,range_operator,range_color_id FROM range_color

WHILE(0<(SELECT COUNT(1) FROM @temp1))
BEGIN

DECLARE @operator VARCHAR(10),@range_color_id INT

SELECT TOP 1 @operator=Operator,@range_color_id=range_color_id FROM @temp1
INSERT INTO @temp
EXEC ('select range_color,CASE WHEN '+ @val +' '+@operator+' range_number  
THEN 1 else 0 END,range_number,'+@val+'- range_number from range_color WHERE  
range_color_id='+@range_color_id)
DELETE TOP (1) FROM @temp1
END

SELECT * FROM @temp  WHERE flag=1  ORDER BY ABS(diff)

请您查看以下查询。

declare @PassingValues int = 0
declare @MatchingRange int

select top 1 @MatchingRange = range_number from #RangeColor where range_number = @PassingValues
order by range_color_id     
if(@@ROWCOUNT <= 0)
begin
if(@MatchingRange is not null)
begin
    select top 1 * from #RangeColor where range_number <= @MatchingRange 
    order by range_color_id
end
else
begin
    Select top 1 @MatchingRange = range_number from #RangeColor where range_number < @PassingValues 
    order by range_number desc      
    if(@MatchingRange IS NULL)
    begin
        select top 1 @MatchingRange = range_number from #RangeColor where range_number > @PassingValues 
        order by range_number                   
        select top 1 * from #RangeColor where range_number > @MatchingRange 
        order by range_color_id
    end
    else
    begin
        select top 1 * from #RangeColor where range_number <= @MatchingRange 
        order by range_color_id desc        
    end
end
end
else
begin
    select top 1 * from #RangeColor where range_number = @PassingValues
    order by range_color_id     
end

好吧,如果您打算打印这些值在范围内,您可以使用以下存储过程:

Create Proc MyProc(@Range Int)
As
Begin
Select @Range As RangeValue, Case When @Range = 0 Then
        'Red'
        When @Range > 0 And @Range<5 Then
        'Blue'
        When @Range >= 5 And @Range <8 Then
        'Purple'
        When @Range >= 8 And @Range <12 Then
        'Orange'
        When @Range >=12 Then
        'Green'
        End As ColorName
End
Go
 -- execute procedure..
Exec MyProc 3

我建议将您的 table 更改为更易于解释和查询的内容。以下语句创建新的 table 并将您的规则转换为新格式。稍后您会看到查询这个新的 table.

是多么容易

我建议的table每种颜色都有下限+上限:

CREATE TABLE UpdatedRangeColor (
    range_color_id INT PRIMARY KEY,
    range_color VARCHAR(50) NOT NULL,
    LowerLimit INT,
    HigherLimit INT)

这会将当前规则转换为新规则 table:

CREATE TABLE UpdatedRangeColor (
    range_color_id INT PRIMARY KEY,
    range_color VARCHAR(50) NOT NULL,
    LowerLimit INT,
    HigherLimit INT)


;WITH HigherRule AS
(
    SELECT
        R.*,
        IsRuleHigher = CASE WHEN R.range_operator LIKE '%>%' THEN 1 ELSE 0 END
    FROM
        range_color AS R
),
TemporaryLimits AS
(
    select 
        R.*,
        TemporaryLowerLimit = CASE WHEN R.IsRuleHigher = 1 THEN R.range_number END,
        TemporaryHigherLimit = CASE WHEN R.IsRuleHigher = 0 THEN R.range_number END,
        Partition = ROW_NUMBER() OVER (
            PARTITION BY
                CASE WHEN R.IsRuleHigher = 1 THEN 1 ELSE 2 END
            ORDER BY
                ABS(R.range_number))
    from 
        HigherRule AS R
)
INSERT INTO UpdatedRangeColor (
    range_color_id,
    range_color,
    LowerLimit,
    HigherLimit)
SELECT
    T.range_color_id,
    T.range_color,
    LowerLimit = CASE 
        WHEN T.IsRuleHigher = 1 THEN T.TemporaryLowerLimit
        ELSE LAG(T.TemporaryHigherLimit, 1, -999) OVER (PARTITION BY T.IsRuleHigher ORDER BY T.Partition DESC) END,
    HigherLimit = CASE
        WHEN T.IsRuleHigher = 1 THEN LEAD(T.TemporaryLowerLimit, 1, 999) OVER (PARTITION BY T.IsRuleHigher ORDER BY T.Partition ASC)
        ELSE T.TemporaryHigherLimit END
FROM
    TemporaryLimits AS T

插入的行如下:

range_color_id  range_color LowerLimit  HigherLimit
1               RED         -999        0
2               BLUE        0           5
3               PURPLE      5           8
4               ORANGE      8           12
5               GREEN       12          999

然后您可以简单地发出带有 2 个条件的直接查询(确保查看应包含等号的位置):

DECLARE @ParameterValue FLOAT = 5.648

SELECT
    *
FROM
    UpdatedRangeColor AS U
WHERE
    @ParameterValue >= U.LowerLimit AND
    @ParameterValue < U.HigherLimit

结果:

range_color_id  range_color LowerLimit  HigherLimit
3               PURPLE      5           8

这种方法的缺点是维护这个新的 table,您必须在插入新值或更新时保持记录的一致性(或使用此过程将原始行转换为新格式添加新记录的时间)。