SQL Server:来自多行的最新属性集和日期
Posted
技术标签:
【中文标题】SQL Server:来自多行的最新属性集和日期【英文标题】:SQL Server: Most recent attribute set and date from multiple rows 【发布时间】:2021-01-23 06:05:04 【问题描述】:我有一个包含几条不完整记录的表格,每条记录都暗指某个客户 - 客户类型 (Type)、年度采购量 (A)、客户位置 (B)、二级承包商 (C)、频率 (D) 等。这些记录充当有关每个客户的不完整信息的快照,并被分配一个年份和唯一的快照 ID (snapID)。
我的目标是为每个客户和客户类型(每个客户 ID 可能有多个客户类型)创建一个由每个字段(以及与该快照 ID 关联的年份)的最新非零、非空值组成的单个记录, 否则为空白。
在我探索的不同阶段,我认为解决方案与分区、子查询、数据透视、案例或简单的排序依据/分组依据有关,但我太新手了,无法理解不同的用例.
样本数据:
[custID] [Type] [snapID] [A] [B] [C] [D] [Year]
1025 InPerson 5 0 (NULL) Cavs Weekly 2020
1025 InPerson 6 275 (NULL) Heat Weekly 2019
1025 InPerson 7 600 Cleveland Cavs (NULL) 2018
7256 Online 8 (NULL) Akron (NULL) (NULL) 2020
7256 InPerson 9 375 (NULL) Nets (NULL) 2020
7256 Online 10 400 (NULL) Thunder Monthly 2015
7256 InPerson 11 (NULL) (NULL) Magic (NULL) 2014
期望的结果:
[custID] [Type] [A] [AYear] [B] [BYear] [C] [CYear] [D] [DYear]
1025 InPerson 275 2019 Cleveland 2018 Cavs 2020 Weekly 2020
7256 InPerson 375 2020 (NULL) (NULL) Nets 2020 (NULL) (NULL)
7256 Online 400 2015 Akron 2020 Thunder 2015 Monthly 2014
【问题讨论】:
道歉。我刚刚编辑了这个问题。用 SQL Server 和 SSMS 标记。谢谢你的建议。 【参考方案1】:这可以使用一些难以理解和调试的嵌套子查询结构来完成。因此,如果您的平台允许,我会采用另一种方式,使用用户定义的函数。
有关确切的语法,请参阅您的 DBMS 文档。我会定义像
这样的函数create function maxAYear (
@custID int,
@type varchar(...)
)
return select max(Year)
from your_table
where custID = @custID
and @type = type
and A is not null
and A <> 0
create function maxA (
@custID int,
@type varchar(...)
)
return select A
from my_table
where custID = @custID
and type = @type
and year = maxAYear(@custID, @type)
然后将我的结果表构建为
select custID, type, maxA(custID, type), maxAYear(custID, type), ...
from (
select distinct custID, type
from my_table
) a
我知道有些人不鼓励使用用户定义的函数。但是我经常使用它们没有任何问题,它们有两个优点:
它们支持易于理解的模块化设计, 它们是可重复使用的, 它们可以单独测试,这不适用于嵌套子查询。【讨论】:
【参考方案2】:这回答了问题的原始版本。
在标准 SQL 中,可以使用last_value(ignore nulls)
:
select t.*
from (select custid, type,
last_value(a ignore nulls) over (partition by custid, type order by year) as a,
last_value(case when a is not null then year end ignore nulls) over (partition by custid, type order by year) as ayear,
last_value(b ignore nulls) over (partition by custid, type order by year) as b,
last_value(case when b is not null then year end ignore nulls) over (partition by custid, type order by year) as byear,
last_value(c ignore nulls) over (partition by custid, type order by year) as c,
last_value(case when c is not null then year end ignore nulls) over (partition by custid, type order by year) as cyear,
last_value(d ignore nulls) over (partition by custid, type order by year) as d,
last_value(case when d is not null then year end ignore nulls) over (partition by custid, type order by year) as dyear,
row_number() over (partition by custid, type order by year desc) as seqnum
from t
) t
where seqnum = 1;
Here 是一个 dbfiddle。
您的问题被标记为“SQL”,它指的是标准 SQL。这是一个标准的 SQL 解决方案。如果这在您的特定数据库中不起作用,请使用适当的数据库标签提出 new 问题。
【讨论】:
非常感谢 Gordon 解决了这个问题,这一直在推动我的极限。不幸的是(我喜欢一个真正的 n00b 忘了提及),我在 SQL Server 中工作,而不是在 Oracle 中工作,并且查询的“last_value([column] ignore nulls)”部分让我很适合。我正在尝试找到与此命令等效的 SQL Server,以挽救您在此处所做的工作。再次感谢您,我找到解决方案后会发布! @aFellowChucker 。 . .我建议您提出一个新的问题,并附上清晰的解释和适当的标签。 我刚刚编辑了问题并更恰当地标记了。再次感谢您的帮助。以上是关于SQL Server:来自多行的最新属性集和日期的主要内容,如果未能解决你的问题,请参考以下文章
powershell 使用FAF技术(批量数据集和内联多线程)快速CSV到SQL Server导入
SQL Server连续日期 - 将多行汇总为连续的开始和结束日期行,而不包含CTE,循环,... s