SQL:比较列以获得集合的精确匹配

SQL:比较列以获得集合的精确匹配,sql,sql-server,tsql,analytics,ssms,Sql,Sql Server,Tsql,Analytics,Ssms,我有一张这样的桌子: RN ID1 ID2 Name Source 1 W76544 945297 1_W_HO HO 2 W76544 945297 1_W_INT Int 1 W76547 945299 3_W_HO HO 2 W76547 945678 3_W_INT Int 1 W76561 NULL Dev_U_W

我有一张这样的桌子:

RN    ID1     ID2     Name            Source
1   W76544  945297  1_W_HO          HO
2   W76544  945297  1_W_INT         Int
1   W76547  945299  3_W_HO          HO
2   W76547  945678  3_W_INT         Int
1   W76561  NULL    Dev_U_W         AD
2   W76561  207283  Dev_W_HO        HO
3   W76561  207283  Dev_W_INT       Int
1   W76562  207284  Dev_R_HO        HO
2   W76562  207284  Dev_R_INT       Int
3   W76562  NULL    Dev_U_R         AD
1   W76563  NULL    Prd_U_W         AD
2   W76563  NULL    Prd_W_HO        HO
3   W76563  NULL    Prd_W_INT       Int
RN    ID1     ID2  Matched   Name            Source
1   W76544  945297   Yes    1_W_HO          HO
2   W76544  945297   Yes    1_W_INT         Int
1   W76547  945299   No     3_W_HO          HO
2   W76547  945678   No     3_W_INT         Int
1   W76561  NULL     No     Dev_U_W         AD
2   W76561  207283   No     Dev_W_HO        HO
3   W76561  207283   No     Dev_W_INT       Int
1   W76562  207284   No     Dev_R_HO        HO
2   W76562  207284   No     Dev_R_INT       Int
3   W76562  NULL     No     Dev_U_R         AD
1   W76563  NULL     Empty  Prd_U_W         AD
2   W76563  NULL     Empty  Prd_W_HO        HO
3   W76563  NULL     Empty  Prd_W_INT       Int
SELECT m.RN,
    m.ID1,
    m.ID2,
    CASE WHEN NOT EXISTS (SELECT 1 FROM MyTable WHERE ID1 = m.ID1 AND ID2 IS NOT NULL) THEN 'Empty'
        ELSE CASE WHEN COUNT(*) OVER(PARTITION BY m.ID1, m.ID2) > 1 THEN 'Yes' 
                ELSE 'No'
            END
    END "Matched",
    m.Name,
    m.Source
FROM MyTable m
我试图找出我们如何确定ID1和ID2集之间的精确匹配。例如,此示例完全匹配:

RN    ID1     ID2     Name            Source
1   *W76544 945297* 1_W_HO          HO
2   *W76544 945297* 1_W_INT         Int
我希望结果如下所示:

RN    ID1     ID2     Name            Source
1   W76544  945297  1_W_HO          HO
2   W76544  945297  1_W_INT         Int
1   W76547  945299  3_W_HO          HO
2   W76547  945678  3_W_INT         Int
1   W76561  NULL    Dev_U_W         AD
2   W76561  207283  Dev_W_HO        HO
3   W76561  207283  Dev_W_INT       Int
1   W76562  207284  Dev_R_HO        HO
2   W76562  207284  Dev_R_INT       Int
3   W76562  NULL    Dev_U_R         AD
1   W76563  NULL    Prd_U_W         AD
2   W76563  NULL    Prd_W_HO        HO
3   W76563  NULL    Prd_W_INT       Int
RN    ID1     ID2  Matched   Name            Source
1   W76544  945297   Yes    1_W_HO          HO
2   W76544  945297   Yes    1_W_INT         Int
1   W76547  945299   No     3_W_HO          HO
2   W76547  945678   No     3_W_INT         Int
1   W76561  NULL     No     Dev_U_W         AD
2   W76561  207283   No     Dev_W_HO        HO
3   W76561  207283   No     Dev_W_INT       Int
1   W76562  207284   No     Dev_R_HO        HO
2   W76562  207284   No     Dev_R_INT       Int
3   W76562  NULL     No     Dev_U_R         AD
1   W76563  NULL     Empty  Prd_U_W         AD
2   W76563  NULL     Empty  Prd_W_HO        HO
3   W76563  NULL     Empty  Prd_W_INT       Int
SELECT m.RN,
    m.ID1,
    m.ID2,
    CASE WHEN NOT EXISTS (SELECT 1 FROM MyTable WHERE ID1 = m.ID1 AND ID2 IS NOT NULL) THEN 'Empty'
        ELSE CASE WHEN COUNT(*) OVER(PARTITION BY m.ID1, m.ID2) > 1 THEN 'Yes' 
                ELSE 'No'
            END
    END "Matched",
    m.Name,
    m.Source
FROM MyTable m
分类。。。Match='Yes',当具有相同ID1的所有组与具有相同ID2的所有组匹配时。Match='No',当具有相同ID1的组不是全部匹配到类似ID2,就是某些ID1的匹配,但集中的其他组根本不匹配到ID2时。Match='Empty',当具有相同ID1的所有组与ID2完全不匹配时

p、 s.RN是由ID1划分和排序的行号

谢谢

@BaconBits,这似乎是你的问题:

1   W10151820   NULL    No  DEV_U_W         AD
2   W10151820   212405  Yes DEV_W_HO    HO
3   W10151820   212405  Yes DEV_W_INTL  Int

你能这样做吗:

RN    ID1     ID2     Name            Source
1   W76544  945297  1_W_HO          HO
2   W76544  945297  1_W_INT         Int
1   W76547  945299  3_W_HO          HO
2   W76547  945678  3_W_INT         Int
1   W76561  NULL    Dev_U_W         AD
2   W76561  207283  Dev_W_HO        HO
3   W76561  207283  Dev_W_INT       Int
1   W76562  207284  Dev_R_HO        HO
2   W76562  207284  Dev_R_INT       Int
3   W76562  NULL    Dev_U_R         AD
1   W76563  NULL    Prd_U_W         AD
2   W76563  NULL    Prd_W_HO        HO
3   W76563  NULL    Prd_W_INT       Int
RN    ID1     ID2  Matched   Name            Source
1   W76544  945297   Yes    1_W_HO          HO
2   W76544  945297   Yes    1_W_INT         Int
1   W76547  945299   No     3_W_HO          HO
2   W76547  945678   No     3_W_INT         Int
1   W76561  NULL     No     Dev_U_W         AD
2   W76561  207283   No     Dev_W_HO        HO
3   W76561  207283   No     Dev_W_INT       Int
1   W76562  207284   No     Dev_R_HO        HO
2   W76562  207284   No     Dev_R_INT       Int
3   W76562  NULL     No     Dev_U_R         AD
1   W76563  NULL     Empty  Prd_U_W         AD
2   W76563  NULL     Empty  Prd_W_HO        HO
3   W76563  NULL     Empty  Prd_W_INT       Int
SELECT m.RN,
    m.ID1,
    m.ID2,
    CASE WHEN NOT EXISTS (SELECT 1 FROM MyTable WHERE ID1 = m.ID1 AND ID2 IS NOT NULL) THEN 'Empty'
        ELSE CASE WHEN COUNT(*) OVER(PARTITION BY m.ID1, m.ID2) > 1 THEN 'Yes' 
                ELSE 'No'
            END
    END "Matched",
    m.Name,
    m.Source
FROM MyTable m

丑陋如罪恶,但我认为这应该有效。

我认为使用分析函数可能更容易:

select id1, id2,
       (case when cnt_1 = cnt2 and min_1_2 = max_1_2 and min_2_1 = max_2_1 and
                  cnt_1 = cnt_2_notnull
             then 'Yes'
             when cnt_2_notnull > 0
             then 'No'
             else 'Empty'
        end) as flag
from (select t.id1, t.id2,
             count(id1) over (partition by id2) as cnt_2_notnull,
             count(*) over (partition by id1) as cnt_1,
             count(*) over (partition by id2) as cnt_2,
             min(id1) over (partition by id2) as min_1_2,
             max(id1) over (partition by id2) as max_1_2,
             min(id2) over (partition by id1) as min_2_1,
             max(id2) over (partition by id1) as max_2_1
      from table t
     ) t;

逻辑是计算id1和id2的每个维度上的值的数量,并比较每个维度上的最小值和最大值。

为了保持事物干净、轻巧且易于理解,将来我将使用CTE来计算匹配的参数

然后我将把结果合并在一起

工作示例:

试试这个:

Create table t(id int, c char(1))

Insert into t values
(1, 'a'),
(1, 'a'),
(2, 'b'),
(2, null),
(3, null),
(3, null),
(4, 'c'),
(4, 'd')

;with cte as(
select id, count(*) c1, count(c) c2, count(distinct c) c3 from t
group by id)
select t.id, t.c, ca.m from t
Cross apply(select case when c2 = 0 and c3 = 0 then 'empty'
            when c1 = c2 and c3 = 1 then 'yes'
            else 'no' end as m
            from cte where cte.id = t.id) ca
输出:

id  c       m
1   a       yes
1   a       yes
2   b       no
2   (null)  no
3   (null)  empty
3   (null)  empty
4   c       no
4   d       no

这个怎么样?请用您的表名替换“YourTableName here”后再试一次好吗

具有 A作为 选择 X.ID1,X.ID2, 按点击次数计数1 从你的表名这里 按X.ID1、X.ID2分组 计数1>1的 , B作为 选择 X.ID1, SUMCASE当X.ID2为空时,则0或1以命中结束, SUMCASE当X.ID2为空时,则1或0结束为空 从你的表名这里 按X.ID1分组 计数1>1的 选择 X.RN,X.ID1,X.ID2, 案例 当A.Hits=B.为空时,则为“空” 当A.Hits=B.Hits+B.Nulls时,则为“是” 否则“不” 结束为[匹配], X[名称],X[来源] 从…起 你的表名在这里 左接A 在…上 A.ID1=X.ID1 A.ID2=X.ID2或A.ID2为空,X.ID2为空 B.ID1=X.ID1上的左连接B;
您的示例数据、解释和期望的输出似乎不匹配。看看W76563。在您的示例数据中,RN1和2在ID1中都有一个值,但根据您的解释,它们只有在没有值时才应该为空。我想你可以在这里用一个分区来利用count distinct,但你的输出不清楚。非常接近,但似乎无法正确识别我编辑问题时使用的示例。也许我跑错了,但这似乎不起作用,将大多数情况标记为“否”。选择的答案简洁而漂亮。更好的练习更多