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:来自多行的最新属性集和日期的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL Server 的多行中查找连续的日期

powershell 使用FAF技术(批量数据集和内联多线程)快速CSV到SQL Server导入

SQL Server连续日期 - 将多行汇总为连续的开始和结束日期行,而不包含CTE,循环,... s

SQL查询获取特定日期和列中最新日期之间的数据

访问具有最新日期的 SQL 唯一记录,包括来自单个表的空日期

SQL Server:从最大日期/最新日期的记录中获取数据