如何识别有效/无效的数字组合,而每个组合被分成多行

时间:2017-05-23 07:59:16

标签: sql sql-server

我有两张桌子

  1. 有效组合范围( ValidationTable
  2. 我的组合验证。 (的 MyListTable
  3. 如何在 MyListTable 中识别VALID或INVALID组合?而每个组合按Id和Type-Id

    分成多行

    在下面的示例中, ValidationTable 中有两种组合, MYListTable 中有两种组合可供验证。

    样本表和预期结果:

    =====================
    ** ValidationTable **
    ===========================================================
    | ValidRangeId | TypeId | ValidNumberFrom | ValidNumberTo |
    ===========================================================
    |      1       |    1   |       0         |     10        |
    |      1       |    2   |       50        |     100       |
    |      1       |    3   |       5         |     999       |
    |      2       |    1   |       100       |     200       |
    |      2       |    2   |       300       |     999       |
    |      2       |    3   |       400       |     999       |
    ===========================================================
    
    ====================
    ** MyListTable **
    ===========================================
    | MyRangeId    | TypeId |    MyNumber     |
    ===========================================
    |     10       |    1   |       8         |
    |     10       |    2   |       75        |
    |     10       |    3   |       500       |
    |     20       |    1   |       1         |
    |     20       |    2   |       400       |
    |     20       |    3   |       500       |
    ===========================================
    
    ====================
    ** EXPACTED RESULT **
    ===========================
    | MyRangeId    | Result   |
    ===========================
    |     10       | Valid    | Combination numbers are in valid range
    |     20       | Invalid  | Combination numbers are NOT in valid range
    ===========================
    

    如何在MyListTable中使用10 !!!

    我的组合成为Id 10,

    MyNumberRange(10)=> 8-75-500

    组合范围变为:

    ValidateRange(1)=> 0-50-5至10-100-999

    ValidateRange(2)=> 100-300-400至200-999-999

    SO MyNumberRange(8-75-500)属于ValidateRange(0-50-5至10-100-999)

    因此10是有效的

    MyListTable中的20如何无效!!!

    我的组合成为Id 20,

    MyNumberRange(20)=> 1-400-500

    组合范围变为:

    ValidateRange(1)=> 0-50-5至10-100-999

    ValidateRange(2)=> 100-300-400至200-999-999

    SO MyNumberRange(1-400-500)不属于ValidateRange(0-50-5至10-100-999也不是100-300-400至200-999-999)

    因此20无效

    这里是上表的SQL :(结果在此SQL中修复,只是为了解释)

    IF OBJECT_ID('tempdb.dbo.#ValidationTable', 'U') IS NOT NULL  DROP TABLE #ValidationTable;
    IF OBJECT_ID('tempdb.dbo.#MyListTable', 'U') IS NOT NULL  DROP TABLE #MyListTable;
    IF OBJECT_ID('tempdb.dbo.#Result', 'U') IS NOT NULL  DROP TABLE #Result;
    
    SELECT * INTO #ValidationTable
    FROM (SELECT 1 ValidRangeId, 1 TypeId, 0 ValidNumberFrom, 10 ValidNumberTo UNION
        SELECT 1 ValidRangeId, 2 TypeId, 50 ValidNumberFrom, 100 ValidNumberTo UNION
        SELECT 1 ValidRangeId, 3 TypeId, 5 ValidNumberFrom, 999 ValidNumberTo UNION
        SELECT 2 ValidRangeId, 1 TypeId, 100 ValidNumberFrom, 200 ValidNumberTo UNION
        SELECT 2 ValidRangeId, 2 TypeId, 300 ValidNumberFrom, 999 ValidNumberTo UNION
        SELECT 2 ValidRangeId, 3 TypeId, 400 ValidNumberFrom, 999 ValidNumberTo) v 
    
    SELECT * INTO #MyListTable
    FROM (SELECT 10 MyRangeId, 1 TypeId, 8 MyNumber UNION
        SELECT 10 MyRangeId, 2 TypeId, 75 MyNumber UNION
        SELECT 10 MyRangeId, 3 TypeId, 500 MyNumber UNION
        SELECT 20 MyRangeId, 1 TypeId, 1 MyNumber UNION
        SELECT 20 MyRangeId, 2 TypeId, 400 MyNumber UNION
        SELECT 20 MyRangeId, 3 TypeId, 500 MyNumber) m
    
    SELECT * INTO #Result
    FROM (SELECT 10 MyRangeId, 'Valid' Result UNION
        SELECT 20 MyRangeId, 'Invalid' Result) r
    
    SELECT * FROM #ValidationTable
    SELECT * FROM #MyListTable
    SELECT * FROM #Result
    

2 个答案:

答案 0 :(得分:1)

请检查一下:

with RI as
(
    select
        distinct(MyRangeId) MyRangeIdDistinct
    from
        MyListTable
)    
select
    RI.MyRangeIdDistinct MyRangeId,
    case
        when
        (
            select count(distinct(VT.ValidRangeId)) from
                ValidationTable VT,
                MyListTable MLT
            where
                RI.MyRangeIdDistinct=MLT.MyRangeId and
                VT.TypeId=MLT.TypeId and
                MLT.MyNumber not between VT.ValidNumberFrom and ValidNumberTo
         ) < (select count(distinct(VT2.ValidRangeId)) from ValidationTable VT2) 
         then
             'Valid'
         else
             'Invalid'
     end Result
from
     RI
order by 1;

答案 1 :(得分:1)

嗯,测试不多,可能不是最佳解决方案,但第一场比赛可以这样添加:

with RI as
(
    select
        distinct(MyRangeId) MyRangeIdDistinct
    from
        MyListTable
)    
select
    RI.MyRangeIdDistinct MyRangeId,
    case
        when
        (
            select count(distinct(VT.ValidRangeId)) from
                ValidationTable VT,
                MyListTable MLT
            where
                RI.MyRangeIdDistinct=MLT.MyRangeId and
                VT.TypeId=MLT.TypeId and
                MLT.MyNumber not between VT.ValidNumberFrom and VT.ValidNumberTo
         ) < (select count(distinct(VT2.ValidRangeId)) from ValidationTable VT2) 
         then
             'Valid'
         else
             'Invalid'
     end Result,
     (
        select Min(VT3.ValidRangeId) from
                ValidationTable VT3,
                MyListTable MLT3
            where
            (
                 select count(distinct(VT4.ValidRangeId)) from
                     ValidationTable VT4,
                     MyListTable MLT4
                 where
                     RI.MyRangeIdDistinct=MLT4.MyRangeId and
                     VT4.TypeId=MLT4.TypeId and
                     MLT4.MyNumber not between VT4.ValidNumberFrom and VT4.ValidNumberTo
             ) = (select count(distinct(VT5.ValidRangeId)) from ValidationTable VT5
                  where VT5.ValidRangeId=VT3.ValidRangeId) 
     ) FirstMatch
from
     RI
order by 1;