微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何一次检索所有祖父母

如何解决如何一次检索所有祖父母

我在 sqlite3(家族债券)中有两个简单的表:

"persons" (id,fname,lname)
“关系”(父母/孩子)

我想让每个孙辈和他们所有的祖父母一起(从 1 到 4 个,取决于孙辈),以便 1 行结果 =

distinct Grand child,Grand parent 1,Grand parent 2,Grand parent 3,Grand parent 4

感谢 Caius Jard,我能够让每个孩子及其祖父母参与另一个明星溢出问题。但是,到目前为止,我有
1 行 = 孙辈,1 位祖父母(因此最多需要 4 行才能获得孩子的所有祖父母)。

SELECT c.fname,c.lname,gp.fname,gp.lname  
FROM relations p_c
INNER JOIN relationships gp_p ON gp_p.child = p_c.parent 
INNER JOIN persons gp ON gp.id = gp_p.parent 
INNER JOIN persons c ON c.id = p_c.child
ORDER BY c.id;

我如何编辑它,以便在一行结果中获得每个孙子和所有祖父母?

如果可能,只使用 SELECT (+ count/distinct)、WHERE (+in/exists)、INNER/LEFT JOIN、GROUP BY (+have)、ORDER BY。

解决方法

我们可以通过一种称为条件聚合的技术将行转换为列:

假设你有一个结果集:

x,y
1,hello
2,goodbye

如果你是这样写的:

SELECT x,CASE WHEN x = 1 THEN y END as x1,CASE WHEN x = 2 THEN y END as x2
FROM ...

你会得到这个:

x,x1,x2
1,hello,NULL
2,NULL,goodbye

一列只有一个值,其余为空。如果你然后使用例如MAX,丢弃空值:

SELECT
  MAX(CASE WHEN x = 1 THEN y END) as x1,MAX(CASE WHEN x = 2 THEN y END) as x2
FROM ...

你会得到

x1,x2
hello,goodbye

我们不得不放弃 x,因为我们不能把它放在那里,否则我们必须将它分组,这将防止行折叠


现在对于您的查询,我们可能需要添加其他信息,因为我们需要一些 CASE WHEN 信息。你没有表示我们可以随意在那里扔一个行号。希望 persons 包含性别指标,因为 4 个祖父母是一男一女产生的两男两女的结果(所以我们有 MM - 父亲的父亲,MF - 父亲的母亲,FM 和 FF 等)>

SELECT ...  
FROM relations p_c
INNER JOIN relationships gp_p ON gp_p.child = p_c.parent 
INNER JOIN persons gp ON gp.id = gp_p.parent 
INNER JOIN persons p ON p.id = p_c.parent 
INNER JOIN persons c ON c.id = p_c.child

我们现在可以查询每个级别的家谱的性别:

SELECT c.name as child,CASE WHEN gp.gender = 'm' AND p.gender = 'm' THEN gp.name END AS fathersfather,CASE WHEN gp.gender = 'm' AND p.gender = 'f' THEN gp.name END AS fathersmother,CASE WHEN gp.gender = 'f' AND p.gender = 'm' THEN gp.name END AS mothersfather,CASE WHEN gp.gender = 'f' AND p.gender = 'f' THEN gp.name END AS mothersmother
FROM relations p_c
INNER JOIN relationships gp_p ON gp_p.child = p_c.parent 
INNER JOIN persons gp ON gp.id = gp_p.parent 
INNER JOIN persons p ON p.id = p_c.parent 
INNER JOIN persons c ON c.id = p_c.child

这将给孩子和祖父母名字的对角数组。您可以使用以下命令将其压缩为每个孩子的一行:

SELECT c.name as child,MAX(CASE WHEN gp.gender = 'm' AND p.gender = 'm' THEN gp.name END) AS fathersfather,MAX(CASE WHEN gp.gender = 'm' AND p.gender = 'f' THEN gp.name END) AS fathersmother,MAX(CASE WHEN gp.gender = 'f' AND p.gender = 'm' THEN gp.name END) AS mothersfather,MAX(CASE WHEN gp.gender = 'f' AND p.gender = 'f' THEN gp.name END) AS mothersmother
FROM relations p_c
INNER JOIN relationships gp_p ON gp_p.child = p_c.parent 
INNER JOIN persons gp ON gp.id = gp_p.parent 
INNER JOIN persons p ON p.id = p_c.parent 
INNER JOIN persons c ON c.id = p_c.child
GROUP BY c.name
,

我建议使用 GROUP_CONCAT() 并为所有祖父母获取 1 列,而不是祖父母的 4 列:

SELECT p.fname,p.lname,GROUP_CONCAT(gp.fname || ' ' || gp.lname,'|')
FROM persons p
INNER JOIN relationships r1 ON r1.child = p.id
INNER JOIN relationships r2 ON r2.child = r1.parent
INNER JOIN persons gp ON r2.parent = gp.id
GROUP BY p.id

代码要简单得多。
如果您希望返回所有人员,即使是没有祖父母的人员,请使用 LEFT 联接而不是 INNER 联接。

,

假设有四个祖父母,您可以枚举它们并汇总:

SELECT fname,lname,MAX(CASE WHEN seqnum = 1 THEN grandparent_name END) as grandparent_1,MAX(CASE WHEN seqnum = 2 THEN grandparent_name END) as grandparent_2,MAX(CASE WHEN seqnum = 3 THEN grandparent_name END) as grandparent_3,MAX(CASE WHEN seqnum = 4 THEN grandparent_name END) as grandparent_4
FROM (SELECT c.id,c.fname,c.lname,gp.fname || ' ' || gp.lname as grandparent_name,ROW_NUMBER() OVER (PARTITION BY c.id ORDER BY gp.fname,gp.lanme) as seqnum 
      FROM relations p_c JOIN
           relationships gp_p
           ON gp_p.child = p_c.parent JOIN
           persons gp
           ON gp.id = gp_p.parent 
           persons c
           ON c.id = p_c.child
     ) cgp
GROUP BY fname,id;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。