英文:
How to find other parent table entries that have exact same values and number of child table entries?
问题
SQL: 从子表中的值返回一个基于父表的ID。(SQL)(MySQL)
我有两个表,父表 (ID),和子表 (Value_A, Value_B, ParentID),它们之间有一个一对多的关系(一个父项可以有多个子项)。
给定父表的一个ID,我该如何找到其他在父表中具有相同值和子表条目数量的条目?
父表
| ID |
|---- |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
子表:
| Value_a| Value_b| ParentId|
|:---- |:------:| -----:|
| 10 | 25 | 1 |
| 20 | 75 | 1 |
| 10 | 50 | 2 |
| 20 | 50| 2|
| 10 | 75 | 3|
| 20 | 25 | 3|
| 10 | 25 | 4|
| 20 | 75| 4|
| 30 | 25 | 4|
| 10 | 25 | 5|
| 20 | 75 | 5|
| 10 | 25 | 6|
| 20 | 75 | 6|
给定父ID 1,预期结果是 5, 6。
我曾经查询过返回具有相同 Value_A 但不同 Value_B 的父项,反之亦然。
英文:
SQL: Returning an id from a table based off the values in the child table.(SQL)(MySQL)
I have 2 tables, Parent (ID), and Child (Value_A, Value_B, ParentID), with a 1->many relationship (Parent has multiple children).
Given an Id for the Parent table, how would I find other entries in the parent table that have the same values and number of Child table entries?
Parent
ID |
---|
1 |
2 |
3 |
4 |
5 |
6 |
Child:
Value_a | Value_b | ParentId |
---|---|---|
10 | 25 | 1 |
20 | 75 | 1 |
10 | 50 | 2 |
20 | 50 | 2 |
10 | 75 | 3 |
20 | 25 | 3 |
10 | 25 | 4 |
20 | 75 | 4 |
30 | 25 | 4 |
10 | 25 | 5 |
20 | 75 | 5 |
10 | 25 | 6 |
20 | 75 | 6 |
Given Parent ID 1 the expected result is 5, 6.
I've had queries that return Parents with the same Value_A but not Value_B and vice versa.
答案1
得分: 1
这是一个经典的无余数关系划分问题。
有多种解决方案,但经典的方法首先是获取原始集合中的总行数。然后将该集合与每个潜在的集合进行左连接,并确保所有行都匹配,并且匹配的数量与原始集合中的数量相同。
对于带余数版本,只需将LEFT JOIN
更改为INNER JOIN
,并将HAVING
更改为
HAVING COUNT_BIG(*) >= @count -- 至少有这么多匹配
英文:
This is a classic Relational Division Without Remainder question.
There are a number of solutions, but the classic one is to first get the total number rows in the original set. Then left-join that set to each potential set, and ensure that all rows match as well as there being the same number of matches as there are in the original set.
DECLARE @yourId int = 1;
DECLARE @count bigint = (SELECT COUNT(*) FROM Child WHERE ParentId = @yourId);
SELECT *
FROM Parent p
WHERE p.Id <> @yourId
AND EXISTS (SELECT 1
FROM Child other
LEFT JOIN Child cThis
ON cThis.Value_a = other.Value_a
AND cThis.Value_b = other.Value_b
AND cThis.ParentId = @yourId
WHERE other.ParentId = p.Id
HAVING COUNT_BIG(*) = @count -- same number of matches
AND COUNT_BIG(*) = COUNT_BIG(cThis.ParentId) -- all rows match
);
For a With Remainder version, just change the LEFT JOIN
to INNER JOIN
, and change the HAVING
to
HAVING COUNT_BIG(*) >= @count -- at least that number of matches
答案2
得分: 0
为了比较值集合,可以使用汇总后的字符串并进行比较。
请尝试以下代码:
with ChildValues as (
select Parentid
,string_agg(value_a,',') within group (order by value_a) sA
,string_agg(value_b,',') within group (order by value_a) sB
from Child
group by ParentId
)
select *
from ChildValues t1
left join ChildValues t2
on t1.sA=t2.sA and t1.sB=t2.sB
and t1.ParentId<>t2.ParentId
where t1.Parentid=1
结果:
Parentid | sA | sB | Parentid | sA | sB |
---|---|---|---|---|---|
1 | 10,20 | 25,75 | 5 | 10,20 | 25,75 |
1 | 10,20 | 25,75 | 6 | 10,20 | 25,75 |
或者完整查询:
with ChildValues as (
select Parentid
,string_agg(value_a,',') within group (order by value_a) sA
,string_agg(value_b,',') within group (order by value_a) sB
from Child
group by ParentId
)
select t1.ParentId, string_agg(t2.parentId,',') within group(order by t2.parentId) Ids
from ChildValues t1
left join ChildValues t2 on t1.sA=t2.sA and t1.sB=t2.sB and t1.ParentId<>t2.ParentId
where t1.Parentid=1
group by t1.ParentId
ParentId | Ids |
---|---|
1 | 5,6 |
英文:
To compare sets of values, can use aggregated strings and compare them.
Try this
with ChildValues as (
select Parentid
,string_agg(value_a,',') within group (order by value_a) sA
,string_agg(value_b,',') within group (order by value_a) sB
from Child
group by ParentId
)
select *
from ChildValues t1
left join ChildValues t2
on t1.sA=t2.sA and t1.sB=t2.sB
and t1.ParentId<>t2.ParentId
where t1.Parentid=1
Result
Parentid | sA | sB | Parentid | sA | sB |
---|---|---|---|---|---|
1 | 10,20 | 25,75 | 5 | 10,20 | 25,75 |
1 | 10,20 | 25,75 | 6 | 10,20 | 25,75 |
Or full query
with ChildValues as (
select Parentid
,string_agg(value_a,',') within group (order by value_a) sA
,string_agg(value_b,',') within group (order by value_a) sB
from Child
group by ParentId
)
select t1.ParentId, string_agg(t2.parentId,',') within group(order by t2.parentId) Ids
from ChildValues t1
left join ChildValues t2 on t1.sA=t2.sA and t1.sB=t2.sB and t1.ParentId<>t2.ParentId
where t1.Parentid=1
group by t1.ParentId
ParentId | Ids |
---|---|
1 | 5,6 |
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论