【问题标题】:Column based on a range in animal dataset- sql基于动物数据集中范围的列 - sql
【发布时间】:2020-08-18 17:22:25
【问题描述】:

表:

num       value      category      name
503       8978       bird          woodpecker
502       7812       animal        
502       7812       animal        
501       7812       animal        
500       7812       animal        panther
499       7812       animal        
498       7812       animal     
467       7812       animal        elephant           

valuecategory 列的partition by 内,应创建输出列,如下所示:
name 不为null 时,output 列占用name 的值,并在num 列的加2 和减2 范围内填充相同的值。
例如,500 有name not null,500-2=498 和 500+2=502,在 498 到 502 的范围内,输出填充为panther

输出:

  num       value      category      name             output
  503       8978       bird          woodpecker       
  502       7812       animal                         panther
  502       7812       animal                         panther
  501       7812       animal                         panther
  500       7812       animal        panther          panther
  499       7812       animal                         panther
  498       7812       animal                         panther
  467       7812       animal        elephant         elephant 

【问题讨论】:

  • 您需要解决的另外几个问题。为什么 501 和 502 不包含“啄木鸟”?它们也落在名称不为空的行的 +/- 2 内。这个选择背后的逻辑是什么?当 name 在 2 个或多个连续 num 值中不为空时会发生什么?如果 502 行中的 1 行包含非空名称但另一行不包含,或者任何时候 2 行仅在名称上不同而其中一个为空,会发生什么情况?
  • 为什么 501 和 502 不包含“啄木鸟”? ----- Because it's based on partition by value and category ,如果 name 在 2 个或多个连续 num 值中不为 null 会发生什么? --- output would be null,如果 502 行中的 1 行包含非空名称但另一行没有,会发生什么情况,----- output is null when name is not null,谢谢@Belayer
  • pc_pyr,你试试查询吗?
  • (1) 为什么num 列中有重复项? (2) 你用的是什么数据库?
  • select version(); 给你什么?

标签: sql postgresql window-functions


【解决方案1】:

您可以使用range 窗框:

select t.*,
       coalesce(name,
                max(name) over (partition by category
                                order by num
                                range between 2 preceding and 2 following
                               )
               ) as imputed_name
from t;

Here 是一个 dbfiddle。

编辑:

在 Postgres 中,range 窗口框架对“前面”和“后面”的支持是相对较新的。在旧版本中,横向连接可能是最简单的方法:

select t.*,
       coalesce(t.name, t2.name) as imputed_name
from t left join lateral
     (select t2.name
      from t t2
      where t2.category = t.category and
            t2.name is not null and
            t2.num between t.num - 2 and t.num + 2
      limit 1
     ) t2
     on 1=1
order by num desc;

Here 是这个版本的数据库小提琴。

【讨论】:

  • 我收到一个错误Invalid operation: RANGE clause of window functions not yet implemented;
  • 感谢@Gordon Linoff,将使用您更新的查询进行尝试
【解决方案2】:

尝试使用带大小写的窗口函数:

select num,value,category,name,output from
(
--if num is in range [match_number-2, match_number+2] then get animal's name
select *, CASE when num>=(match_number-2) and num<=(match_number+2) then max_nam else NULL end as output from
 (
 --find num matching name
 select *,max( case when name=max_nam then num else 0 end )over (partition by value,category) match_number from
  (
  --find name (not null) partition by value,category 
   select *,max(name)over(partition by value,category)max_nam from Table
  )X
 )Y
)Z

【讨论】:

  • @pc_pyr:如果该查询对您有用,那么您肯定没有使用 Postgres
  • Postgres 中没有iif
  • 只是改成大小写)
  • 是的@OlgaRomantsova,它对我不起作用,因为我在 postgres 上,将尝试更新您的答案,谢谢。
猜你喜欢
  • 2010-09-08
  • 2013-12-19
  • 2015-03-26
  • 1970-01-01
  • 2019-05-11
  • 1970-01-01
  • 2021-12-05
  • 2021-07-05
  • 1970-01-01
相关资源
最近更新 更多