TSQL比较两个集合

时间:2010-09-07 19:00:26

标签: sql sql-server sql-server-2005 tsql

当给出两组时

s1 = {a,b,c,d} s2 = {b,c,d,a}

(即)

TableA

Item
a
b
c
d

TableB

Item
b
c
d
a

如何编写Sql查询以显示“tableA和tableB中的元素相等”。 [不使用SP或UDF]

输出

Elements in TableA and TableB contains identical sets

6 个答案:

答案 0 :(得分:9)

使用:

SELECT CASE 
         WHEN   COUNT(*) = (SELECT COUNT(*) FROM a) 
            AND COUNT(*) = (SELECT COUNT(*) FROM b) THEN 'Elements in TableA and TableB contains identical sets'
         ELSE 'TableA and TableB do NOT contain identical sets'
       END
  FROM (SELECT a.col
          FROM a
        INTERSECT
        SELECT b.col
          FROM b) x 

测试:

WITH a AS (
  SELECT 'a' AS col
  UNION ALL
  SELECT 'b'
  UNION ALL
  SELECT 'c'
  UNION ALL
  SELECT 'd'),
     b AS (
  SELECT 'b' AS col
  UNION ALL
  SELECT 'c'
  UNION ALL
  SELECT 'd'
  UNION ALL
  SELECT 'a')
SELECT CASE 
         WHEN   COUNT(*) = (SELECT COUNT(*) FROM a) 
            AND COUNT(*) = (SELECT COUNT(*) FROM b) THEN 'yes'
         ELSE 'no'
       END
  FROM (SELECT a.col
          FROM a
        INTERSECT
        SELECT b.col
          FROM b) x 

答案 1 :(得分:5)

这样的事情,使用FULL JOIN

SELECT
  CASE 
    WHEN EXISTS (
      SELECT * FROM s1 FULL JOIN s2 ON s1.Item = s2.Item
      WHERE s1.Item IS NULL OR s2.Item IS NULL
      )
    THEN 'Elements in tableA and tableB are not equal'
    ELSE 'Elements in tableA and tableB are equal'
  END

这具有在第一次不匹配时短路的优点,不同于需要对每个表进行2次完全扫描的其他解决方案(一次用于COUNT(*),一次用于JOIN / INTERSECT)。

估计成本明显低于其他解决方案。

答案 2 :(得分:3)

我的怪物:

;with SetA as
(select 'a' c union
select 'b' union
select 'c') 
, SetB as 
(select 'b' c union
select 'c' union
select 'a' union 
select 'd'
) 
select case (select count(*) from (
select * from SetA except select * from SetB
union 
select * from SetB except select * from SetA
)t)
when 0 then 'Equal' else 'NotEqual' end 'Equality'

答案 3 :(得分:3)

注意,我要使用交叉加入。

Declare @t1 table(val varchar(20))
Declare @t2 table(val varchar(20))


insert into @t1 values ('a')
insert into @t1 values ('b')
insert into @t1 values ('c')
insert into @t1 values ('d')


insert into @t2 values ('c')
insert into @t2 values ('d')
insert into @t2 values ('b')
insert into @t2 values ('a')

select 
    case when 
    count(1) = 
    (((Select count(1) from @t1) 
    + (Select count(1) from @t2)) / 2.0) 
    then 1 else 0 end as SetsMatch  from 
@t1 t1 cross join @t2 t2 
where t1.val = t2.val

答案 4 :(得分:2)

可以使用EXCEPT和案例

来完成
select 
   case 
     when count (1)=0 
        then 'Elements in TableA and TableB contains identical sets' 
     else 'Nope' end from (
       select item from s1
      EXCEPT 
       select item from s2
) b

答案 5 :(得分:1)

由于这个帖子对我很有帮助,我以为我会分享我的解决方案。

我有类似的问题,或许比这个特定的单组比较更普遍适用。我试图找到一个元素的id,该元素具有一组与多元素项的查询集匹配的多元素子元素。

相关的架构信息是:

table events, pk id
table solutions, pk id, fk event_id -> events
table solution_sources, fk solutionid -> solutions
   columns unitsourceid, alpha

查询:找到id为110的事件的解决方案,该事件具有与ss_tmp中的(unitsourceid,alpha)集匹配的solution_sources集。 (我相信,这也可以在没有tmp表的情况下完成。)

解决方案:

with solutionids as (
  select y.solutionid from (
     select ss.solutionid, count(ss.solutionid) x 
        from solutions s, solution_sources ss 
        where s.event_id = 110 and ss.solutionid = s.id 
        group by ss.solutionid
  ) y where y.x = ( select count(*) from ss_tmp )
) 
select solutionids.solutionid  from solutionids where
(
select case
   when count(*) = ( select count(*) from ss_tmp ) then true
   else false
   end
    from 
       ( SELECT unitsourceid, alpha FROM solution_sources 
            where solutionid = solutionids.solutionid
          INTERSECT
         SELECT unitsourceid, alpha FROM ss_tmp ) x
)

针对4个项目的测试查询和具有匹配解决方案的测试数据库(相同数量的子元素,每个匹配),几个完全不匹配的解决方案和1个具有3个匹配子元素的解决方案进行测试,1解决方案包含所有4个匹配的子元素,另外还有一个子元素,以及1个包含4个子元素的解决方案,其中4个子元素中的3个与查询匹配。只返回了真匹配的id。

非常感谢 -Linus