我有一个如下的数据集。 Fiddle URL
我需要使用上表中的运算符获取给定数字的颜色。
例如;
当我调用函数getColor(6)
时,应该返回PURPLE
。
当我调用函数getColor(0)
时,应该返回RED
。
我该如何实现?
答案 0 :(得分:2)
最简单的解决方案是使用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)
答案 1 :(得分:1)
您可以尝试以下查询吗?
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)
答案 2 :(得分:1)
请您查看下面的查询。
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
答案 3 :(得分:1)
我建议您将表格更改为更易于解释和查询的内容。以下语句创建新表并将您的规则转换为新格式。稍后,您将看到查询此新表有多么容易。
我建议的表格对每种颜色都有下限和上限:
CREATE TABLE UpdatedRangeColor (
range_color_id INT PRIMARY KEY,
range_color VARCHAR(50) NOT NULL,
LowerLimit INT,
HigherLimit INT)
这会将当前规则转换为新表:
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
这种方法的缺点是维护了这个新表,在插入新值或更新时,您必须保持记录的一致性(或使用此过程在每次添加新记录时将原始行转换为新格式)。
答案 4 :(得分:0)
好吧,如果您打算打印这些值在范围内,则可以使用以下存储过程:
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