Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何编写SQL以使用GROUPBY函数从多行中提取最新的非空数据?_Sql_Sql Server - Fatal编程技术网

如何编写SQL以使用GROUPBY函数从多行中提取最新的非空数据?

如何编写SQL以使用GROUPBY函数从多行中提取最新的非空数据?,sql,sql-server,Sql,Sql Server,我想为MS SQL编写SQL,以便为每个number 以下是数据的外观: 这就是我想要输出的方式: 更新: 此外,如果我更改INSERT语句并包含TYPE列,是否会更好?我是否可以获取每种类型的最新记录并运行任何聚合函数(MIN/MAX)?: 这是相当棘手的。一种方法是使用相关子查询或横向联接: select * from (select distinct number from t) n outer apply (select top (1) t2.city from

我想为MS SQL编写SQL,以便为每个
number

以下是数据的外观:

这就是我想要输出的方式:

更新:

此外,如果我更改INSERT语句并包含TYPE列,是否会更好?我是否可以获取每种类型的最新记录并运行任何聚合函数(MIN/MAX)?:


这是相当棘手的。一种方法是使用相关子查询或横向联接:

select *
from (select distinct number from t) n outer apply
     (select top (1) t2.city
      from t t2
      where t2.number = n.number and t2.city is not null
      order by t2.record_date desc
     ) c outer apply
     (select top (1) t2.region
      from t t2
      where t2.number = n.number and t2.region is not null
      order by t2.record_date desc
     ) r outer apply
     . . .
不幸的是,您必须一次只做一列

SQL标准有一个构造
ignorenulls
,它可以与
LAG()
一起使用,以准确地支持您想要做的事情

顺便说一下,另一种方法是条件聚合“


我不确定这些备选方案中的哪一个会有更好的性能。

您可以取消将列拆分为行,计算第一个值,然后再向后旋转。取消拆分会为您忽略空值。但首先您需要将所有值都转换为varchar,以避免类型冲突。

UPD: 更新模型的代码和代码

with a as (
  select
    1 as num,
    cast(null as varchar(100)) as city,
    cast(null as varchar(100)) as region,
    cast('John' as varchar(100)) as name,
    cast(null as varchar(100)) as assigned,
    cast(null as varchar(100)) as reportsto,
    'Person' as type_,
    '2020-11-10 05:12' as recorddt
  union all
  select 1, null, null, 'Smith', null, null, 'Person', '2020-11-10 05:13' union all
  select 1, 'London', 'EU', null, null, null, 'Location', '2020-11-10 05:15' union all
  select 1, null, null, null, 'Team A', '425', 'Assignment', '2020-11-10 05:17' union all
  select 1, null, null, null, 'Team X', '234', 'Assignment', '2020-11-10 05:18' union all
  select 2, 'LA', 'US', null, null, null, 'Location', '2020-11-10 05:22'
)
, row_num as (
  select
    a.*,
    row_number() over(partition by num, type_ order by recorddt desc) as rn
  from a
)
select
  num,
  max(city) as city,
  max(region) as region,
  max(name) as name,
  max(assigned) as assigned,
  max(reportsto) as reportsto
from row_num
where rn = 1
group by num

您是否建议对“如何在此处插入数据”的设计进行任何小的更改以简化选择?@ShivamAgrawal…最简单的解决方案是重复表中的所有值,而不是使用
NULL
表示值没有更改。这还有一个优点,即支持
NULL
作为任何列中的有效值umns。您的设计更改将使它变得更好,因为这样您将
行数
按类型划分为
,只选择第一条记录,然后应用
最大值
,每个数字有一个值。@astentx,您能给我举个例子吗?我不明白如何只取第一条记录?我需要排序吗在那之前,除了你,没有人知道你的“桌子”是什么(我随便用这个词)也不表示输出的每一行所表示的内容。每一行是否表示一个城市?一项任务?您的样本数据非常小,任何建议都将基于该样本进行假设。当伦敦有多行时会发生什么情况?史密斯有多行吗?不同的日期?表中的数字表示什么?您的输出是否包含姓氏——如果是,您如何知道要包含哪个名称值?@ShivamAgrawal更新了mu对这种情况的回答。假设您在
类型
类型的实体的相应列中没有空值作为实值。但在任何表结构的情况下,在单个catchall中存储完全不同类型的实体都是不好的主意表,并对select语句中的值进行解码。最好对不同的实体类型使用不同的表,并使用一个路由表,其中包含它们之间的关系以及相应的检查和引用完整性…尽管这是一种聪明的方法,但这要求所有列都是相同的类型。
with a as (
  select
    1 as num,
    cast(null as varchar(100)) as city,
    cast(null as varchar(100)) as region,
    cast('John' as varchar(100)) as name,
    cast(null as varchar(100)) as assigned,
    cast(null as varchar(100)) as reportsto,
    '2020-11-10 05:12' as recorddt
  union all
  select 1, null, null, 'Smith', null, null, '2020-11-10 05:13' union all
  select 1, 'London', 'EU', null, null, null, '2020-11-10 05:15' union all
  select 1, null, null, null, 'Team A', '425', '2020-11-10 05:17' union all
  select 1, null, null, null, 'Team X', '234', '2020-11-10 05:18'
)
, unp as (
  select
    num,
    col,
    val,
    row_number() over(partition by num, col order by recorddt desc) as rn
  from a
  unpivot(
    val for col in (City, Region, Name, Assigned, ReportsTo)
  ) q
)
select
  num,
  [city],
  [region],
  [name],
  [assigned],
  [reportsto]
from (
  select *
  from unp
  where rn = 1
) a
pivot(
  max(val) for col in ([city], [region], [name], [assigned],[reportsto])
) p


| num | city   | region | name  | assigned | reportsto |
+-----+--------+--------+-------+----------+-----------+
| 1   | London | EU     | Smith | Team X   | 234       |
with a as (
  select
    1 as num,
    cast(null as varchar(100)) as city,
    cast(null as varchar(100)) as region,
    cast('John' as varchar(100)) as name,
    cast(null as varchar(100)) as assigned,
    cast(null as varchar(100)) as reportsto,
    'Person' as type_,
    '2020-11-10 05:12' as recorddt
  union all
  select 1, null, null, 'Smith', null, null, 'Person', '2020-11-10 05:13' union all
  select 1, 'London', 'EU', null, null, null, 'Location', '2020-11-10 05:15' union all
  select 1, null, null, null, 'Team A', '425', 'Assignment', '2020-11-10 05:17' union all
  select 1, null, null, null, 'Team X', '234', 'Assignment', '2020-11-10 05:18' union all
  select 2, 'LA', 'US', null, null, null, 'Location', '2020-11-10 05:22'
)
, row_num as (
  select
    a.*,
    row_number() over(partition by num, type_ order by recorddt desc) as rn
  from a
)
select
  num,
  max(city) as city,
  max(region) as region,
  max(name) as name,
  max(assigned) as assigned,
  max(reportsto) as reportsto
from row_num
where rn = 1
group by num