查看差异表

问题描述 投票:0回答:1

让我们想象两个表 - T_Name、T_nameAttributes

T_名称

姓名 姓名ID
莎拉 2
马修 3

T_name属性

姓名ID 属性ID 价值
2 3 红苹果
2 5 20 美元

最初从他们那里检索数据看起来像这样

select * 
from T_name 
left join T_nameAttributes 
    on T_name.NameID = T_nameAttributes.NameID 
    and AttributeID = 3 

Sara, 3, Red Apple

每天,这些值都会保存到带有附加“日期”列的同一表模式中,这里一切都很好,我可以轻松地在请求的日期检索值

这里的问题 - 我想节省数据库空间并仅存储更改的值,所以我的日志表现在看起来像这样:

T_姓名日志

日期 姓名 姓名ID
2023-01-01 莎拉 2
2023-10-05 莎拉 2 // 名称已更改

T_name属性日志

日期 属性ID 姓名ID 价值
2023-01-01 3 2 红苹果
2023-10-04 3 2 青苹果 // 值改变了
2023-01-01 5 2 20 美元
2023-02-12 5 2 0 美元
2023-10-09 5 2 70 美元

问题:两个表都可以在随机日期更改其值,我想检索一个连接表,其中的行基于一个月中的每一天

Select date, name, value 
from T_NameLog 
left join T_nameAttributesLog <...> 
where date between '2023-10-02' and '2023-10-05' 
and AttributeID = 3

预期结果:

日期 名字 属性
2023-10-02 莎拉 红苹果
2023-10-03 莎拉 红苹果
2023-10-04 莎拉 青苹果
2023-10-05 莎拉 青苹果
sql sql-server sql-server-2012
1个回答
0
投票

首先为每个日期生成一行。然后使用

OUTER APPLY
TOP
子句来获取表的最新行。我编写了查询,以便它可以查找所有名称和属性,而不是仅查找一个名称和一个属性。这是通过
TOP (1) WITH TIES
ORDER BY RANK()
结合完成的。

如果您只需要一个名称或一个属性,只需注释掉

WHERE
子句中的 ID 条件即可。 (但在这种情况下,有
TOP (1)
就足够了,没有
WITH TIES
子句,只有
ORDER BY [Date] DESC
。)

with 
  days as 
  (
    select cast('2023-10-02' as date) as dt,
           cast('2023-10-05' as date) as last_dt
    union all
    select dateadd(day, 1, dt),
           last_dt
    from days
    where dt < last_dt
  )
select days.dt, n.name, na.value
from days
outer apply
(
  select top (1) with ties
    nl.name,
    nl.nameid
  from t_namelog nl
  where nl.[Date] <= days.dt
  -- and nl.nameid = 2
  order by rank() over (partition by nl.nameid order by nl.[Date] desc)
) n
outer apply
(
  select top (1) with ties
    nal.value,
    nal.attributeid
  from t_nameattributeslog nal
  where nal.nameid = n.nameid
  and nal.[Date] <= days.dt
  -- and nal.attributeid = 3
  order by rank() over (partition by nal.attributeid order by nal.[Date] desc)
) na
order by days.dt, n.nameid, na.attributeid;

演示:https://dbfiddle.uk/m1nCfwxX

© www.soinside.com 2019 - 2024. All rights reserved.