当给出两个集合
s1 = {a,b,c,d} s2 = {b,c,d,a}
(即)
TableA
Item
a
b
c
d
TableB
Item
b
c
d
a
如何编写Sql查询以显示“表A和表B中的元素相等”。[不使用SP或UDF]
输出
Elements in TableA and TableB contains identical sets
当给出两个集合
s1 = {a,b,c,d} s2 = {b,c,d,a}
(即)
TableA
Item
a
b
c
d
TableB
Item
b
c
d
a
如何编写Sql查询以显示“表A和表B中的元素相等”。[不使用SP或UDF]
输出
Elements in TableA and TableB contains identical sets
使用:
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
Test with:
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
使用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
我的怪物:
;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'
注意,我将使用交叉连接(Cross Join)。
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
可以使用EXCEPT和CASE来实现
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
由于这个帖子对我非常有用,所以我想分享一下我的解决方案。
我遇到了一个类似的问题,比这个具体的单集比较更普遍适用。我试图找到一个元素的 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)的集合相匹配。(我认为这也可以在没有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个子元素中有3个与查询匹配的解决方案。只返回真正匹配的ID。
非常感谢 -Linus
使用EXCEPT语句
使用EXCEPT语句测试两个集合是否包含相同的行时,需要在两个方向上执行EXCEPT(A EXCEPT B 和 B EXCEPT A)。如果任何一个比较返回记录,则表示这些集合不同。如果两个比较都没有返回记录,则它们相同。
这个好处是可以对任意数量的特定列进行比较,并且处理NULL值时会隐式地进行处理,而无需跳过 hoops 进行比较。
这样做的一个好的使用案例是验证保存记录集是否正确,特别是当影响现有记录集时。
SELECT IsMatching = (1 ^ convert(bit, count(*)))
FROM (
SELECT Mismatched = 1 -- Can be any column name
FROM (
SELECT Item -- Can have additional columns
FROM TableA
EXCEPT
SELECT Item -- Can have additional columns
FROM TableB
) as A
UNION
SELECT Mismatched = 1 -- Can be any column name
FROM (
SELECT Item -- Can have additional columns
FROM TableB
EXCEPT
SELECT Item -- Can have additional columns
FROM TableA
) as A
) as A