【问题标题】:Oracle SQL : family tree views using treesOracle SQL:使用树的家谱视图
【发布时间】:2017-05-16 19:39:03
【问题描述】:

我想创建一个视图,让我拥有一些最年长的人的孙子孙女。 问题是我找不到在 sql 中翻译这句话的方法:“谁有一些”。

我只在一张非常基本的桌子上工作:

Person : number(type number)、lastname、firstname、dateofbirth、gender、mother(type number)、father(type number)。

这是我尝试做的:

我试图创建一个视图,让我知道有孙子的最年长的人(但这不是这里要做的)

  CREATE OR REPLACE
  VIEW oldestone
  AS SELECT number FROM persons
     WHERE (sysdate-dateofbirth)/365 >= ALL
     (SELECT (sysdate-dateofbirth)/365 FROM persons)
     AND EXISTS (SELECT * FROM persons
                  WHERE level=3 
            START WITH number = number
            CONNECT BY PRIOR number = father OR PRIOR numero = mother);

并且有了第一个视图的数量我可以得到孙子:

CREATE OR REPLACE
VIEW grandchildren
AS SELECT firstname,lastname FROM persons
   WHERE level=3 
   START WITH number = (SELECT number FROM oldestone)
   CONNECT BY PRIOR number = father OR PRIOR number = mother;

问题是我知道我不是在翻译:有一些的最年长的人的孙子孙女。因为在我第一次看到 number = number 时,我想引用我的 select 子句第 3 行的编号,但我知道事实并非如此。

提前感谢你们的帮助!

克里斯。

【问题讨论】:

    标签: oracle tree family-tree


    【解决方案1】:

    如果您将方向反转为“向上”阅读家谱,而不是“向下”,您可以从孙辈转到他们的父母,然后再转到祖父母。当您这样做时,在最里面的子查询中,您可以使用connect_by_root() 运算符“记住”孙子的名字,并将它们与不同级别祖先的出生日期相关联(他们自己的出生日期在第 1 级,他们父母的出生日期)出生日期在第 2 级,他们祖父母的出生日期在第 3 级)。

    在中间子查询中,我选择层次查询在第 3 级生成的行——这将显示祖父母的出生日期。我使用分析函数在同一查询中记录最小出生日期。 (你不需要“年龄”——“最老”是指最早的出生日期!)

    我尽可能经济地编写查询,在每个阶段只保留产生所需结果所需的列(最年长的祖父母的孙辈的名字);当您选择子子查询和中间子查询并分别运行它们时,要了解其工作原理,您可能需要添加更多列以查看发生了什么。

    我在 WITH 子句中创建了一些非常简单的测试数据(不是解决方案的一部分);您可能希望使用更有趣的输入进行测试。祝你好运!

    with
         person ( id, last_name, first_name, dob, mother, father ) as (
           select  1, 'Doe', 'John', date '1990-03-02',  2,  3 from dual union all
           select  2, 'Doe', 'Anne', date '1962-11-21',  4,  5 from dual union all
           select  3, 'Doe', 'Alan', date '1960-02-23',  6,  7 from dual union all
           select  4, 'Orf', 'Jean', date '1953-10-11',  8,  9 from dual union all
           select  5, 'Orf', 'Stan', date '1952-09-06', 10, 11 from dual union all
           select 22, 'Sun', 'Ryan', date '1968-02-21', 23, 24 from dual union all
           select 23, 'Sun', 'Mary', date '1934-12-09', 26, 27 from dual
         )
    --  end of test data; solution (SQL query) begins below this line
    select last_name, first_name
    from   (
             select last_name, first_name, dob, min(dob) over () as min_dob
             from   (
                      select connect_by_root(last_name)  as last_name ,
                             connect_by_root(first_name) as first_name, dob, level as lvl
                      from   person
                      connect by id in (prior mother, prior father)
             ) 
             where  lvl = 3
    )
    where  dob = min_dob
    ;
    
    LAST_NAME  FIRST_NAME
    ---------  ----------
    Doe        John
    

    【讨论】:

      【解决方案2】:

      表:

      创建表 FAMILYTREE (id int, name varchar(50), MOTHERID int, FATHERID int); /

      插入 FAMILYTREE (id, MOTHERID, FATHERID, name) 值 (1, null, null, '我的祖父'); 插入 FAMILYTREE (id, MOTHERID, FATHERID, name) 值 (2, NULL, NULL, '我的祖母'); 插入 FAMILYTREE (ID, MotherID, FatherID, Name) VALUES (3, 10, 9, 'My Mother'); 插入 FAMILYTREE (ID, MotherID, FatherID, Name) VALUES (4, 2, 1, 'My Father'); 插入 FAMILYTREE (ID, MotherID, FatherID, Name) VALUES (5, 3, 4, 'Me'); 插入 FAMILYTREE (ID, MotherID, FatherID, Name) VALUES (6, 12, 11, '我的妻子'); 插入 FAMILYTREE (ID, MotherID, FatherID, Name) VALUES (7, 3, 4, 'My Brother'); 插入 FAMILYTREE (ID, MotherID, FatherID, Name) VALUES (8, 6, 5, 'My son'); 插入 FAMILYTREE (ID, MotherID, FatherID, Name) VALUES (9, NULL, NULL, 'My Mother Grand Father'); 插入 FAMILYTREE (ID, MotherID, FatherID, Name) VALUES (10, NULL, NULL, 'My Mother Grand Mother'); 插入 FAMILYTREE (ID, MotherID, FatherID, Name) VALUES (11, null, null, 'My Wife Grand Father'); 插入 FAMILYTREE (id, MOTHERID, FATHERID, name) 值 (12, null, null, 'My Wife Grand Mother'); 犯罪; /

      SQl:

      WITH FamilyCTE(ID,name,MotherID,FATHERID,FatherName,MOTHERNAME,LVL) 作为 ( 选择 F。*, null 作为父亲,
      null 作为 MOTHERNAME,0 作为 LVL 来自 FAMILYTREE F 其中 F.FATHERID 为空 并且 f.MotherID 为空 联合所有 选择 f.ID, f.Name AS ParentName, f.MotherID, F.父亲, c.命名为父名, C2.name 为 MOTHERNAME, 等级 + 1 来自 FAMILYTREE F INNER JOIN FamilyCTE c ON F.FatherID = c.ID 在 f.MotherID = c2.ID 上的 INNER JOIN FamilyTree c2 )

      从FAMILYCTE中选择*;

      【讨论】:

      • A code-only answer is not high quality。虽然此代码可能很有用,但您可以通过说明其工作原理、工作方式、何时应该使用以及它的局限性来改进它。请编辑您的答案以包括解释和相关文档的链接。
      猜你喜欢
      • 2012-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-31
      • 2023-03-24
      • 1970-01-01
      • 2011-01-14
      相关资源
      最近更新 更多