给出下表:
------------ ------------
| BA | | CA |
------+----- ------+-----
| BId|| AId| | CId|| AId|
------+------ ------+-----
| B1 | 2 | | C1 | 2 |
| B1 | 3 | | C2 | 2 |
| B2 | 2 | | C2 | 3 |
| B2 | 4 | | C3 | 4 |
| B2 | 5 | | C3 | 5 |
------------ ------------
我该如何编写查询以仅返回那些(DISTINCT)CId,其中具有相同CId的任何CA行集合都从BA中相似的行集合中找到(AId的)完全匹配?
在上面的示例中,应返回C2,因为CA中具有[C2,2]和[C2,3]的行(可以将其称为{(n,2),(n,3)的集合) }?)在BA中找到一个完全匹配的内容:它的前两行-[B1,2]和[B1,3](我们可以将此集合称为{(m,2),(m,3)}吗?)>
答案 0 :(得分:1)
可以使用CA
和BA
的CTE计算元素数量。然后,您可以通过以下方式获取完整行:
with ca_info as (
select
cid
, count(*) as ccount
from ca
group by cid
),
ba_info as (
select
bid
, count(*) as bcount
from ba
group by bid
)
select
*
from
ba
join ca on (ba.aid = ca.aid)
join ba_info on ba.bid=ba_info.bid
join ca_info on ca.cid=ca_info.cid
where ccount = bcount
结果
bid aid cid aid bid bcount cid ccount
B1 2 C2 2 B1 2 C2 2
B1 3 C2 3 B1 2 C2 2
如果您只对C2
本身感兴趣,则可以进一步限制结果集:
with ca_info as (
select
cid
, count(*) as ccount
from ca
group by cid
),
ba_info as (
select
bid
, count(*) as bcount
from ba
group by bid
)
select
distinct ca.cid
from
ba
join ca on (ba.aid = ca.aid)
join ba_info on ba.bid=ba_info.bid
join ca_info on ca.cid=ca_info.cid
where ccount = bcount
要获得子集/超集,可以更改强制执行集合相等的条件:
where ccount <= bcount
这将返回所有集合,其中Bx至少与Cy一样多:
bid aid cid aid bid bcount cid ccount
B1 2 C1 2 B1 2 C1 1
B1 2 C2 2 B1 2 C2 2
B1 3 C2 3 B1 2 C2 2
B2 2 C1 2 B2 3 C1 1
B2 2 C2 2 B2 3 C2 2
B2 4 C3 4 B2 3 C3 2
B2 5 C3 5 B2 3 C3 2
答案 1 :(得分:1)
执行此操作的一种方法是使用JOIN
和COUNT
。您首先要计算CIds(每个CIds重复多少次)。然后,对BIds执行相同的操作。然后,您加入BA并链接(AIds)和COUNT。您的目标是匹配ID及其AId的数量。
示例:
DECLARE
@a TABLE(id INT)
INSERT INTO @a VALUES
(1),
(2),
(3),
(4),
(5),
(6)
DECLARE
@b TABLE(id CHAR(2))
INSERT INTO @b VALUES
('B1'),
('B2'),
('B3')
DECLARE
@c TABLE(id CHAR(2))
INSERT INTO @c VALUES
('C1'),
('C2'),
('C3')
DECLARE
@ba TABLE(BId CHAR(2), AId INT)
INSERT INTO @ba VALUES
('B1',2),
('B1', 3),
('B2', 2),
('B2', 4),
('B2', 5)
DECLARE
@ca TABLE(CId CHAR(2), AId INT)
INSERT INTO @ca VALUES
('C1',2),
('C2',2),
('C2',3),
('C3',4),
('C3',5)
SELECT DISTINCT CId
FROM (
SELECT *
, COUNT(*) OVER(PARTITION BY CId) cnt
FROM @ca ca
) c
LEFT JOIN (
SELECT *
, COUNT(*) OVER(PARTITION BY BId) cnt
FROM @ba ba
) b ON b.AId = c.AId AND b.cnt = c.cnt
WHERE
b.cnt IS NOT NULL
因此,在示例中,C2重复了2次,在BA中,B1也重复了2次。这是第一个条件,第二个条件是匹配两个AIds,如果它们相同,则您具有组匹配。
答案 2 :(得分:1)
我认为最简单的解决方案使用窗口函数:
select ca.cid, ba.bid
from (select ca.*, count(*) over (partition by cid) as cnt
from ca
) ca join
(select ba.*, count(*) over (partition by bid) as cnt
from ba
) ba
on ca.aid = ba.aid and ca.cnt = ba.cnt
group by ca.cid, ba.bid, ca.cnt
having ca.cnt = count(*) -- all match
Here是db <>小提琴。
结果集都是匹配的cid
/ bid
对。
这里的逻辑非常简单。对于每个cid
和bid
,子查询都会计算aid
的计数。此数字必须匹配。
然后join
在aid
上-这是一个内部联接,因此仅生成匹配对。最后的group by
用于生成匹配计数,以查看是否与所有aid
相符。
此特定版本假定每个表中的行都是唯一的,尽管如果不是这种情况,可以轻松调整查询。