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

Posted

技术标签:

【中文标题】如何识别有效/无效数字组合,而每个组合被拆分为多行【英文标题】:How To Identify Valid/Invalid Number Combination Whereas Each Combination Is Splitted Into Multi Rows 【发布时间】:2017-05-23 07:59:16 【问题描述】:

我有两张桌子

    有效组合范围(ValidationTable) 我的验证组合。 (MyListTable)

如何识别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
===========================

10 如何在 MyListTable 中有效!!!

我的组合变成了 Id 10,

MyNumberRange(10) => 8-75-500

而组合范围变成:

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

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

所以 MyNumberRange (8-75-500) 属于 ValidateRange(0-50-5 到 10-100-999)

因此 10 是有效的

如何 20 在 MyListTable 中无效!!!

我的组合变成了 ID 20,

MyNumberRange(20) => 1-400-500

而组合范围变成:

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

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

所以 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

【问题讨论】:

MyRangeId 是否应该与ValidRangeId 具有相同的值?请多解释一下你是如何得到这些预期结果的。解释为什么 10 有效而 20 无效。 MyRangeId 是否应该与 ValidRangeId 具有相同的值?答案是没有不同的 ID 评论时不确定是否需要大写,表示你在喊。使用 bold 来添加重点而不是大写。 我很抱歉....!!!更新的问题,我解释了请审查许多 thxxx 【参考方案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;

【讨论】:

MyRangeId 是否应该与 ValidRangeId 具有相同的值? ****所以答案是=没有两个表都有自己的ID 那么如何识别对应的记录呢?为什么 1 属于 10 而不是 20? Ids 在两个表中都没有任何作用,只接受它的帮助来组合数字,需要更多关于你的 Q 的细节“为什么 1 属于 10 而不是 20?”谢谢 在我看来,您正在根据 ValidRangeId=1 的有效记录范围验证 MyRangeId=10 的记录。如果您要针对 (2,2,300,999) 验证记录 (10, 2, 75),那么它将失败,但您仍然希望 MyRangeId=10 为“有效”。这就是我的问题,如何找到特定的 MyListTable 记录对应的验证记录? 更新了问题以解释 10 是如何有效而 20 是无效的,请查看。许多thxx【参考方案2】:

好吧,没有太多测试,可能不是最佳解决方案,但可以通过这种方式添加 First Match:

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;

【讨论】:

它与样本一起工作,但不适用于我正在使用的实际表,在 FirstMatch 中总是返回 NULL .... 有什么遗漏或者您可以查看一下吗?谢谢

以上是关于如何识别有效/无效数字组合,而每个组合被拆分为多行的主要内容,如果未能解决你的问题,请参考以下文章

熊猫:将列中的列表拆分为多行[重复]

生成所有总和组合

在 arm neon 中有效地重新洗牌和组合 16 个 3 位数字

如何找到添加两个变量的所有可能组合,每个变量都附加到一个乘数,总和为一个给定的数字(cin)?

如何在Access查询中将多行的文本值组合到一个单元格中[重复]

查询功能测试的测试点汇总