使用SQL Server 2012,我有一个类似这样的分类表:
prodName class1min class1max class2min class2max class3min class3max
---------------------------------------------------------------------------------
prod A 1.5 1.8 1.8 2.1 2.1 2.5
prod B 3.6 3.9 3.9 4.5 4.5 5.6
prod C 2.7 3.2 3.2 3.6 3.6 4.2
etc...
给定产品名称和值,我需要找到我的值所属的分类(1,2或3)。
即。我有一个产品B项,其值为4.1。我只需要能够确定它属于第2类。
到目前为止,我已经尝试根据选择的产品创建unpivot表,如下所示:
产品B:
class value
------------------
class1min 3.6
class1max 3.9
class2min 3.9
class2max 4.5
class3min 4.5
class3max 5.6
然后通过插入我的值和排序,我至少能够看到分类。
class value
------------------
class1min 3.6
class1max 3.9
class2min 3.9
myvalue 4.1
class2max 4.5
class3min 4.5
class3max 5.6
我仍然无法通过代码隔离它,我认为可能有更好的方法。
注意:在平局的情况下,我想要较低的分类。
答案 0 :(得分:2)
您可以取消数据,然后执行比较。由于您使用的是SQL Server 2012,因此您可以使用CROSS APPLY轻松地将min
/ max
列中的{@ 1}} / select prodname, class, [min], [max]
from yourtable
cross apply
(
values
('class1', class1min, class1max),
('class2', class2min, class2max),
('class3', class3min, class3max)
) c(class, [min], [max])
列展开:
DECLARE @Prod VARCHAR(32) = 'Prod B',
@val DECIMAL(10,2) = 4.1;
select prodname, class, [min], [max]
from yourtable
cross apply
(
values
('class1', class1min, class1max),
('class2', class2min, class2max),
('class3', class3min, class3max)
) c(class, [min], [max])
where prodname = @Prod
and @val > [min]
and @val <= [max]
见Demo。一旦数据被取消,您就可以比较您的价值以找到该类。如果您有更多分类,则可以在子查询中轻松添加更多值:
{{1}}
答案 1 :(得分:1)
由于只有三个可能的类,因此您可以使用CASE
表达式完成此任务:
DECLARE @Prod VARCHAR(32) = 'Prod B', @val DECIMAL(10,2) = 4.1;
SELECT [Class] = CASE WHEN @val <= class1max THEN 'Class1'
WHEN @val > class3Min THEN 'Class3' ELSE 'Class2' END
FROM dbo.tableName
WHERE ProdName = @Prod;
现在我们知道“问题”是你实际上有9个分类,而不是问题中陈述的3个分类,这仍然可以扩展:
DECLARE @Prod VARCHAR(32) = 'Prod B', @val DECIMAL(10,2) = 4.1;
SELECT [Class] = CASE WHEN @val <= class1max THEN 'Class1'
WHEN @val > class2Min AND @val <= class2Max THEN 'Class2'
WHEN @val > class3Min AND @val <= class3Max THEN 'Class3'
WHEN @val > class4Min AND @val <= class4Max THEN 'Class4'
WHEN @val > class5Min AND @val <= class5Max THEN 'Class5'
WHEN @val > class6Min AND @val <= class6Max THEN 'Class6'
WHEN @val > class7Min AND @val <= class7Max THEN 'Class7'
WHEN @val > class8Min AND @val <= class8Max THEN 'Class8'
ELSE 'Class9' END
FROM dbo.tableName
WHERE ProdName = @Prod;
如果问题在于代码太多,那么你可以考虑改变设计。
答案 2 :(得分:0)
如已评论,您可以简单地将数据规范化为多个表。 e.g。
Product
--------
id_Product
name
moreProductRelatedColumns
ProductClassification
--------------
id_Classification
classCode
fk_productId
min
max
然后你可以选择:
Select classCode
from Products join ProductClassification pc on id_Product = fk_productId
where value between pc.min and pc.max
在当前的表设计中,您可以使用嵌套的CASE WHEN语句。但是我建议使用规范化的表设计,因为在没有重写查询的情况下添加或删除Products中的类没有问题。
答案 3 :(得分:0)
DECLARE @target_product varchar(32) = 'prod B'
DECLARE @target_value decimal(9,2) = 4.1
SELECT LEFT([class],6)
FROM MyTable
UNPIVOT([value] FOR [class] IN (
[class1min],[class1max],
[class2min],[class2max],
[class3min],[class3max]
)) p1
WHERE @target_product = [prodName]
GROUP BY prodName,LEFT([class],6)
HAVING @target_value >= MIN([value]) AND @target_value < MAX([value])
答案 4 :(得分:0)
好吧,既然你问,一个标准化的方法可能看起来像这样[在[prodname,class]上形成PK] ......
prodName class min max
prod A 1 1.5 1.8
prod B 1 3.6 3.9
prod C 1 2.7 3.2
prod A 2 1.8 2.1
prod B 2 3.9 4.5
prod C 2 3.2 3.6
prod A 3 2.1 2.5
prod B 3 4.5 5.6
prod C 3 3.6 4.2