4

如果你有父表

create table parent (
  pid int not null,
  name varchar(255)
)

和一个父子连接表

create table parent_child (
  pid int not null,
  cid int not null,
  foreign key (pid) references parent(pid),
  foreign key (cid) references child(cid)
)
create table child(
  cid int not null,
  name varchar(255)
)

如何在以下列表('dave','henry','myriam','jill')中找到所有孩子都有名字的所有父母的名字。

如果他们有一个不同名字的孩子,我不想看到父母,但如果他们有 1 个或多个孩子并且他们的所有孩子的名字都在列表中,我想看到父母的名字。

我确实找到了这个https://stackoverflow.com/a/304314/1916621这将帮助我找到一个有这些名字的孩子的父母,但我无法弄清楚只有孩子名字的父母如何该列表的一个子集。

如果有人知道不同方法的性能权衡,则加分。

4

2 回答 2

3
SELECT 
    p.pid, 
    p.name
FROM 
    parent p
WHERE NOT EXISTS (
    SELECT *
    FROM 
        parent_child pc 
        JOIN child c 
            ON pc.cid = c.cid
            AND c.name NOT IN ('dave','henry','myriam','jill')
    WHERE 
        p.pid = pc.pid
) AND EXISTS (
    SELECT *
    FROM 
        parent_child pc 
        JOIN child c 
            ON pc.cid = c.cid
            AND c.name IN ('dave','henry','myriam','jill')
    WHERE 
        p.pid = pc.pid
)

另一种方法...没有子查询,但DISTINCT需要额外的方法来消除parent加入parent_child表的记录重复。

SELECT DISTINCT
    p.pid, 
    p.name
FROM 
    parent p 
    JOIN parent_child pc_exists ON pc_exists.pid = p.pid
    JOIN child c_exists 
        ON c_exists.cid = pc_exists.cid
        AND c_exists.name IN ('dave','henry','myriam','jill')
    LEFT JOIN parent_child pc_notExists ON pc_notExists.pid = p.pid
    LEFT JOIN child c_notExists 
        ON c_notExists.cid = pc_notExists.cid
        AND c_notExists.name NOT IN ('dave','henry','myriam','jill')
WHERE
    c_notExists.cid IS NULL
于 2012-12-19T21:38:46.430 回答
1

这是我的适度赌注:

示例表:

家长

PID     NAME
1       dad john
2       mum sandy
3       dad frank
4       mum kate
5       mum jean

孩子

CID     NAME
11      dave
22      maryam
33      henry
44      maryam
16      jill
17      lina
23      jack
34      jill
55      dave

父子

PID     CID
1       11
1       16
1       17
2       22
3       33
4       44
2       23
5       55
3       34

询问:

select p.pid, p.name, 
group_concat(c.name) as children
from parent as p
inner join parent_child as pc
on p.pid = pc.pid
join child as c
on pc.cid = c.cid
where c.name
in ('dave','henry','maryam','jill')
group by p.pid
;

结果:

PID     NAME        CHILDREN
1       dad john    dave,jill
2       mum sandy   maryam
3       dad frank   henry,jill
4       mum kate    maryam
5       mum jean    dave

使用 REGEXP 和 GROUP_CONCAT

它比SQLinfind_in_setSQL 要好得多。我所做的更改,我将列表用作comma delimitted string;)

*但这里的问题是:必须在逗号分隔的字符串中找到 group_concat 字符串顺序。* 除非我们REGEXP提高效率 :)

询问:

select x.pid, x.name,
x.children from(
select p.pid, p.name, 
group_concat(c.name) as children,
  count(c.name) as counts
from parent as p
inner join parent_child as pc
on p.pid = pc.pid
join child as c
on pc.cid = c.cid
group by p.pid) as x
where 'dave,maryam,henry,jill'
REGEXP x.children
;

结果:

PID     NAME        CHILDREN
3       dad frank   henry,jill
4       mum kate    maryam
5       mum jean    dave

* SQLFIDDLE

于 2012-12-19T21:58:52.843 回答