找到具有完全相同值和子表条目数量的其他父表条目如何?

huangapple go评论76阅读模式
英文:

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
);

db<>fiddle

For a With Remainder version, just change the LEFT JOIN to INNER JOIN, and change the HAVING to

    HAVING COUNT_BIG(*) &gt;= @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,&#39;,&#39;) within group (order by value_a) sA
  ,string_agg(value_b,&#39;,&#39;) 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&lt;&gt;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,&#39;,&#39;) within group (order by value_a) sA
  ,string_agg(value_b,&#39;,&#39;) within group (order by value_a) sB
from Child
group by ParentId
  ) 
select t1.ParentId, string_agg(t2.parentId,&#39;,&#39;) 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&lt;&gt;t2.ParentId
where t1.Parentid=1
group by t1.ParentId
ParentId Ids
1 5,6

huangapple
  • 本文由 发表于 2023年5月23日 01:42:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76308712.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定