如何从主从表中获取最后一条记录

How to get last record from Master-Details tables

我有一个 table 有 3 columns.

create table myTable
(
    ID  int Primary key,
    Detail_ID   int references myTable(ID) null, -- reference to self
    Master_Value    varchar(50) -- references to master table
)

这个table有如下记录:

insert into myTable select 100,null,'aaaa'
insert into myTable select 101,100,'aaaa'
insert into myTable select 102,101,'aaaa'
insert into myTable select 103,102,'aaaa' ---> last record

insert into myTable select 200,null,'bbbb'
insert into myTable select 201,200,'bbbb'
insert into myTable select 202,201,'bbbb' ---> last record

记录以 relational 的形式保存 IDDetail_ID 列。 我需要 select 每个 Master_Value 列的最后一条记录。跟随输出:

lastRecordID    Master_Value    Path

202             bbbb            200=>201=>202
103             aaaa            100=>101=>102=>103

提示:

  1. table中的记录未按顺序列出。

  2. 我不能使用max(ID)关键字。因为数据没有排序。(可能 是手动更新的 id 列。)

尝试次数:

我能够准备后续查询并且运行良好:

with Q as
(
select ID ,Detail_ID, Master_Value , 1 RowOrder, CAST(id as varchar(max)) [Path] from myTable where Detail_ID is null
union all
select R.id,R.Detail_ID , r.Master_Value , (q.RowOrder + 1) RowOrder , (q.[Path]+'=>'+CAST(r.id as varchar(max))) [Path] from myTable R inner join  Q ON Q.ID=R.Detail_ID --where r.Dom_ID_RowType=1010
)

select * into #q from Q 

select Master_Value, MAX(RowOrder) lastRecord into #temp from #Q group by Master_Value

select 
    q.ID lastRecordID, 
    q.Master_Value, 
    q.[Path]
from #temp t
    join #q q on q.RowOrder  = t.lastRecord
where
    q.Master_Value = t.Master_Value

但我需要简单的方法(one select)和最佳的方法。

谁能帮帮我?

一种方法使用相关子查询来获取最后一个值(这就是我解释你的问题的方式):

select t.*
from mytable t
where not exists (select 1
                  from mytable t2
                  where t2.master_value = t.master_value and
                        t2.id = t.detail_id
                 );

这 returns 行未被另一行引用。

对于路径,您需要递归 CTE:

with cte as (
      select master_value, id as first_id, id as child_id, convert(varchar(max), id) as path, 1 as lev
      from mytable t
      where detail_id is null
      union all
      select cte.master_value, cte.first_id, t.id, concat(path, '->', t.id), lev + 1
      from cte join
           mytable t
           on t.detail_id = cte.child_id and t.master_value = cte.master_value
      )
select cte.*
from (select cte.*, max(lev) over (partition by master_value) as max_lev
      from cte
     ) cte
where max_lev = lev

Here 是一个 db<>fiddle.