假设我们统计学生成绩所在的区间
【A表设计】:
Result int --学生成绩
StudentName varchar(20) --学生名字
ClassID int --班级ID
【A表数据】:
Result StudentName ClassID
--------- ------------------- -------------
1 A 0
3 B 0
5 C 0
7 D 0
===========================================
【B表设计】:
MinValue int --最小值
MaxValue varchar(20) --最大值
Symbol varchar(20) --组织的符号
ClassID int --班级ID
【B表数据】:
MinValue MaxValue Symbol ClassID
------------- --------------- ------------ -------------
5 NULL X> 0
3 5 <X<= 0
1 3 <X<= 0
1 NULL X<= 0
早期没有B表的时候,我的SQL是这样写的:
SELECT StudentName,
CASE
WHEN Result > 5 THEN 'X>5'
WHEN Result > 3 AND Result <= 5 THEN '3<X<=5'
WHEN Result > 1 AND Result <= 3 THEN '1<X<=3'
WHEN Result <= 1 AND Result <= 5 THEN 'X<=1'
END AS RET
FROM A
返回:
StudentName RET
-------------------- ---------
A X<=1
B 1<X<=3
C 3<X<=5
D X>5
现在因为业务需要就把上面CASE里的逻辑存在B表里了 因为原先写死的那些1、3、5这样的数值要计算 然后动态生成
然后我可以把B表直接的公式拼出来:
SELECT
CASE
WHEN MaxValue IS NULL THEN Symbol + CONVERT(VARCHAR(20), MinValue)
ELSE CONVERT(VARCHAR(20), MinValue) + Symbol + CONVERT(VARCHAR(20), MaxValue)
END AS RET
FROM B
返回:
RET
---------
X<=1
1<X<=3
3<X<=5
X>5
但问题是怎么和A表关联起来啊TAT!!!!!
------解决思路----------------------
表B的设计上要改下,不管你MinValue怎么设计MaxValue,但你要留出两个区间字段这个字段是让你联表做比较用的,他的值是
<=1时,两个都为1,1<X<=3时,为2和3,3<X<=5时为4,5,X>5时为6,以此类推,这样你就能用这字段作为区间去和表A的成绩链接了
------解决思路----------------------
把B表修改下,让Symbol列统一的逻辑
【B表数据】:
MinValue MaxValue Symbol ClassID
------------- --------------- ------------ -------------
5 100000 min < X <= Max 0
3 5 min <X <= Max 0
1 3 min <X <= Max 0
-100000 1 min < X <= Max 0
使用不等值连接,使A表Result处在(MinValue,MaxValue]之间,然后取Symbol
select B.Symbol from A , B where A.Result > B.MinValue and A.Result <= MaxValue
------解决思路----------------------
;with A(Result, StudentName, ClassID) AS
(
SELECT 1, 'A', 0 UNION ALL
SELECT 3, 'B', 0 UNION ALL
SELECT 5, 'C', 0 UNION ALL
SELECT 7, 'D', 0
),
B(MinValue, MaxValue) AS
(
SELECT 5, NULL UNION ALL
SELECT 3, 5 UNION ALL
SELECT 1, 3 UNION ALL
SELECT NULL, 1
)
SELECT A.StudentName
, CASE WHEN B.MinValue IS NULL
THEN 'X<=' + RTRIM(B.MaxValue)
WHEN B.MaxValue IS NULL
THEN 'X>' + RTRIM(B.MinValue)
ELSE RTRIM(B.MinValue) + '<X<=' + RTRIM(B.MaxValue)
END AS RET
FROM A JOIN B ON A.Result>ISNULL(B.MinValue, -1)
AND A.Result<=ISNULL(B.MaxValue, 999999)
/*------结果-------
StudentName RET
A X<=1
B 1<X<=3
C 3<X<=5
D X>5
-------------------*/
------解决思路----------------------
表B设计得不是很方便
IF OBJECT_ID('B')IS NOT NULL
DROP TABLE B
GO
;WITH [CTE](MinValue,MaxValue,Symbol,ClassID)AS(
SELECT 5,NULL,'<X','0'
UNION ALL SELECT'3',5,'<X<=','0'
UNION ALL SELECT'1','3','<X<=','0'
UNION ALL SELECT NULL,1,'X<=','0'
)
SELECT * INTO B FROM CTE
--建议如上设计
SELECT A.StudentName
,ISNULL(CONVERT(VARCHAR(20), B.MinValue),'') + B.Symbol + ISNULL(CONVERT(VARCHAR(20), B.MaxValue),'')RET
FROM A JOIN B ON A.Result>ISNULL(B.MinValue,0) AND A.Result<=ISNULL(B.MaxValue,2147483647)