当前位置: 代码迷 >> Sql Server >> A表存有一列值 B表两列存区间值 求A表值在B表哪个区间内
  详细解决方案

A表存有一列值 B表两列存区间值 求A表值在B表哪个区间内

热度:90   发布时间:2016-04-24 09:12:33.0
【求助】A表存有一列值 B表两列存区间值 求A表值在B表哪个区间内
本帖最后由 Kean1030 于 2015-04-16 16:15:25 编辑
假设我们统计学生成绩所在的区间

【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)
  相关解决方案