如何将值与查找表进行比较

时间:2014-12-26 07:16:55

标签: sql plsql

我有一张表“Mark”,其中包含不同主题的标记。如果标记符合某个特定范围,那么我应该选择相应的排名并在“rank_sub_1”列中插入标记表本身。你能帮我吗,我怎么能在桌子上查看并插入栏目。下面是我的表结构。

**Marks**   
Subject1_Marks  Subject2_Marks
------------------------------
71              22
10              40

**LookupTable**     
Rank    range1  range2
----------------------
9         10    20
8         21    30
7         31    40
6         41    50
5         51    60
4         61    70
3         71    80
2         81    90
1         91    100

现在我想用查找表检查每个主题的标记,查找表包含获得的不同标记的范围和等级。

**Marks**           
Subject1_Marks  Subject2_Marks  Rank_Sub_1  Rank_Sub_2
------------------------------------------------------
71              22      
10              40  

如果标记符合某个特定范围,那么我应该选择相应的等级并在“rank_sub_1”列中插入标记表本身。你能帮我吗,我怎么能在桌子上查看并插入栏目。

3 个答案:

答案 0 :(得分:0)

我认为这个update语句可以做你想要的:

UPDATE Marks m
   SET Rank_Sub_1 = (SELECT l.Rank
                     FROM LookupTable l
                     WHERE m.Subject1_Marks BETWEEN l.range1 AND l.range2)
WHERE EXISTS (
  SELECT 1
  FROM LookupTable l
  WHERE m.Subject1_Marks BETWEEN l.range1 AND l.range2
);

Sample SQL Fiddle

如果您想同时更新Rank_Sub_2的值,可以执行以下操作:

UPDATE Marks m
   SET Rank_Sub_1 = (SELECT l.Rank
                     FROM LookupTable l
                     WHERE m.Subject1_Marks BETWEEN l.range1 AND l.range2)
      ,Rank_Sub_2 = (SELECT l.Rank
                     FROM LookupTable l
                     WHERE m.Subject2_Marks BETWEEN l.range1 AND l.range2)

Sample SQL Fiddle

答案 1 :(得分:0)

(考虑到范围值没有重叠)

获取两个lookuptable实例,首先使用subject1_marks连接,然后使用subject2_marks连接第二个实例。在这里,我没有使用LEFT JOINS,因为我假设您的主题标记肯定会落在1个范围内。如果您对此不确定,请使用左连接并根据您对RANK_SUB_1和RANK_SUB_2列的要求处理空值

WITH LOOKUPTABLE_TMP AS (SELECT * FROM LOOKUPTABLE)
SELECT M.*, L1.RANK AS RANK_SUB_1, L2.RANK AS RANK_SUB_2
FROM MARKS M , LOOKUPTABLE_TMP L1, LOOKUPTABLE_TMP L2
WHERE M.SUBJECT1_MARKS BETWEEN L1.RANGE1  AND L1.RANGE2
AND M.SUBJECT2_MARKS BETWEEN L2.RANGE1  AND L2.RANGE2

然后将数据合并到表MARKS中。

解决方案:

MERGE INTO MARKS MS
USING
(
SELECT M.SUBJECT1_MARKS, M.SUBJECT2_MARKS, L1.RNK AS RANK_SUB_1, L2.RNK AS RANK_SUB_2
FROM MARKS M , LOOKUPTABLE L1, LOOKUPTABLE L2
WHERE M.SUBJECT1_MARKS BETWEEN L1.RANGE1  AND L1.RANGE2
AND M.SUBJECT2_MARKS BETWEEN L2.RANGE1  AND L2.RANGE2
GROUP BY  M.SUBJECT1_MARKS, M.SUBJECT2_MARKS, L1.RNK, L2.RNK
) SUB
ON (MS.SUBJECT1_MARKS=SUB.SUBJECT1_MARKS AND MS.SUBJECT2_MARKS =SUB.SUBJECT2_MARKS)
WHEN MATCHED THEN UPDATE 
SET MS.RANK_SUB_1=SUB.RANK_SUB_1, MS.RANK_SUB_2=SUB.RANK_SUB_2;

根据您问题的详细信息对以下架构和数据进行测试。

CREATE TABLE MARKS (SUBJECT1_MARKS NUMBER, SUBJECT2_MARKS NUMBER , RANK_SUB_1 NUMBER, RANK_SUB_2 NUMBER)

INSERT INTO MARKS (SUBJECT1_MARKS , SUBJECT2_MARKS ) VALUES (71, 22);

INSERT INTO MARKS (SUBJECT1_MARKS , SUBJECT2_MARKS ) VALUES (10, 40);

CREATE TABLE LOOKUPTABLE (RNK NUMBER, RANGE1 NUMBER , RANGE2 NUMBER)

INSERT INTO LOOKUPTABLE VALUES (9, 10, 20);

INSERT INTO LOOKUPTABLE VALUES (8, 21, 30);

INSERT INTO LOOKUPTABLE VALUES (7, 31, 40);

INSERT INTO LOOKUPTABLE VALUES (6, 41, 50);

INSERT INTO LOOKUPTABLE VALUES (5, 51, 60);

INSERT INTO LOOKUPTABLE VALUES (4, 61, 70);

INSERT INTO LOOKUPTABLE VALUES (3, 71, 80);

INSERT INTO LOOKUPTABLE VALUES (2, 81, 90);

INSERT INTO LOOKUPTABLE VALUES (1, 91, 100);

谢谢!

答案 2 :(得分:0)

考虑下面的设计,消除了重叠或间隙的可能性。虽然我通常将此技术用于日期,但任何定义完整序列的数据都将以相同的方式工作。这个想法是你只定义范围的起始位置。可以理解,范围在可能的最后值处停止,小于下一个更高的范围。但是,请注意我添加了第十个等级,以防小于10的值。当然,任何大于100的值都将显示为等级1.

with
Lookup( Rank, Cutoff )as(
    select 1, 91 union all
    select 2, 81 union all
    select 3, 71 union all
    select 4, 61 union all
    select 5, 51 union all
    select 6, 41 union all
    select 7, 31 union all
    select 8, 21 union all
    select 9, 10 union all
    select 10, 0
),
Marks( Mark1, Mark2 )as(
    select  71, 22 union all
    select  10, 40 union all
    select  21, 101
)
select Mark1, l1.Rank as Rank1, Mark2, l2.Rank as Rank2
from    Marks   m
join    Lookup  l1
    on  l1.Cutoff =(
        select  Max( Cutoff )
        from    Lookup
        where   Cutoff <= m.Mark1 )
join    Lookup  l2
    on  l2.Cutoff =(
        select  Max( Cutoff )
        from    Lookup
        where   Cutoff <= m.Mark2 );

输出:

Mark1       Rank1       Mark2       Rank2
----------- ----------- ----------- -----------
71          3           22          8
10          9           40          7
21          8           101         1