我有几行代表person.每个person都有一列bio_mother _uuidbio_father_uuid.我使用this page(我提到这个是因为它在this similar question中被引用)来实现这个连接.

SELECT 
base.uuid base_uuid, base.created_at base_created_at, base.givenname base_givenname, base.bio_mother_uuid base_bio_mother_uuid, base.bio_father_uuid base_bio_father_uuid,
mother.uuid mother_uuid, mother.created_at mother_created_at, mother.givenname mother_givenname, mother.bio_mother_uuid mother_bio_mother_uuid, mother.bio_father_uuid mother_bio_father_uuid,
father.uuid father_uuid, father.created_at father_created_at, father.givenname father_givenname, father.bio_mother_uuid father_bio_mother_uuid, father.bio_father_uuid father_bio_father_uuid
FROM person AS base
LEFT JOIN person AS mother ON base.bio_mother_uuid = mother.uuid
LEFT JOIN person as father ON base.bio_father_uuid = father.uuid;

我希望将行解封到这个Go struct 中

type Person struct{
  UUID string
  Givenname string
  Bio_mother *Person
}

如果我使用上面的查询查询,我会 for each 没有母亲或父亲数据的人获得NULL(这很好),但是当构建母亲/父亲数据时,我最终构建了Person个不完整的实例,因为我在查询中没有"祖父母"数据.我可以通过在代码中实现逻辑来解决这个问题,以再次查询是否存在UICC,但这比在查询中以某种方式这样做会大大降低程序的速度.

这对我来说是一个学习项目,但我不完全确定谷歌什么来一个好的答案.

我如何调整我的查询来处理我的用例并只在一行中返回?这将与递归CTE有关,但我不完全确定如何在查看了一些PostgreSQL教程之后实现它,

编辑: 我意识到丢失数据意味着必须动态命名这些列,或者可能是一些代码?或者是添加前缀?在这个例子中,我只使用"alias".注意Gertrude是如何丢失母数据的,行上有一个间隙.这是因为模式一直是母亲第一,不确定我是否同意模式的建模是有意义的,但这是我现在可以为这些数据想出的模型.如果我朝错误的方向射击,请告诉我

(为了可读性,我还在前几次迭代后将列缩短为"其他东西",我正在乘坐没有WiFi的火车,所以想把这个问题准备好并关闭)

Example Input and Output

示例数据

uuid givenname surname bio_mother_uuid bio_father_uuid
aa david smith ab ac
ab mary smith ad ae
ac john smith af ag
ad gertude snow ah
ae Richard snow
af Katie smith
ag Mathew smith
ah Winston Snow

期望输出

base_uuid base_givenname base_surname base_bio_mother_uuid base_bio_father_uuid mother_uuid mother_givenname mother_surname mother_bio_mother_uuid mother_bio_father_uuid father_uuid father_otherstuff alias_uuid alias_otherstuff alias_uuid alias_otherstuff alias_uuid alias_otherstuff alias_uuid alias_otherstuff alias_uuid alias_otherstuff
aa david smith ab ac ab mary smith ad ae ac john smith.. ad gertrude snow ae richard snow af katie smith ag mathew smith winston snow
ab mary smith ad ae ad gertrude snow ah ae richard snow ah winston snow

推荐答案

Note: This is an answer that reflects the discussion in the comments.

给出示例 struct /数据:

create table people
(
    uuid            text,
    givenname       text,
    surname         text,
    bio_mother_uuid text,
    bio_father_uuid text
);

insert into people (uuid, givenname, surname, bio_mother_uuid, bio_father_uuid)
values ('aa', 'david', 'smith', 'ab', 'ac'),
       ('ab', 'mary', 'smith', 'ad', 'ae'),
       ('ac', 'john', 'smith', 'af', 'ag'),
       ('ad', 'gertude', 'snow', null, 'ah'),
       ('ae', 'Richard', 'snow', null, null),
       ('af', 'Katie', 'smith', null, null),
       ('ag', 'Mathew', 'smith', null, null),
       ('ah', 'Winston', 'Snow', null, null);   

您可以运行递归CTE,如下所示:

with recursive t as (
  select 
       p.uuid    as request_uuid,
       p.uuid                 as uuid,
       p.givenname            as givenname,
       p.surname              as surname,
       p.bio_mother_uuid      as bio_mother_uuid,
       p.bio_father_uuid      as bio_father_uuid,
       0 as generation
       from people p
  union all 
  select 
       child.request_uuid    as request_uuid,
       p.uuid                 as uuid,
       p.givenname            as givenname,
       p.surname              as surname,
       p.bio_mother_uuid      as bio_mother_uuid,
       p.bio_father_uuid      as bio_father_uuid,
       child.generation + 1 as generation       
       from 
       t child join 
       people p on p.uuid = child.bio_mother_uuid or p.uuid = child.bio_father_uuid
  )
  select * from t where request_uuid = 'aa'  and generation < 3  

结果是(fiddle):

request_uuid uuid givenname surname bio_mother_uuid bio_father_uuid generation
aa aa david smith ab ac 0
aa ab mary smith ad ae 1
aa ac john smith af ag 1
aa ad gertude snow ah 2
aa ae Richard snow 2
aa af Katie smith 2
aa ag Mathew smith 2

然后,这将提供填充 struct 所需的所有信息(需要一些自定义代码来完成此操作).像这样在单个查询中检索所有数据可能比运行多个查询更快(但这取决于许多因素).

虽然可能有方法可以在一行中返回所有这些数据,但我觉得这将比上面的方法更难处理(您仍然需要自定义代码来解封,并且需要处理不同数量的列).另一种方法是在JSON中返回 struct (这会使SQL复杂化,但简化Go代码).

Sql相关问答推荐

Postgres,使用iLike运算符从json数组中搜索的工作方式与从常规表中搜索不同

Stack Exchange站点上的最短帖子(按正文长度计算,用户名为原始发帖(SEDE))

仅在特定字符串之后提取两个圆括号之间的计量单位文本

重新组合已排序的日期范围

SQL SELECT MOST NEST TIMESTAMP BEAT ORDER

OVER子句WITH PARTITION BY和ORDER BY忽略主查询的WHERE子句

每年独特口味的冰淇淋数量

多条件SQL排序行为

如何判断小数点后千位是否不为0

DbUp for sqlserver 在 dbo 授权下为非 dbo 用户创建架构

将时间戳四舍五入到最近 10 分钟的查询

PostgreSQL:从多个字段收集特定指标的最后一个条目

SQL SUM Filter逻辑解释

Spark / Hive:如何获取列中正值的百分比?

SQL Server - 判断 ids 层次 struct 中的整数 (id)

PostgreSQL中如何提取以特定字符开头的字符串中的所有单词?

如何按日期和位置对最近 3 个报告日期的 SQL 查询结果进行透视?

SQL:如何从时间戳数据生成时间序列并计算不同事件类型的累计总和?

存储过程 - 动态 SQL 中不同列值的计数

当没有任何行存在时,将一个表中的行插入到另一个表中的更好方法