【问题标题】:Filling in NULLS with previous records - Netezza SQL用以前的记录填充 NULLS - Netezza SQL
【发布时间】:2015-08-14 21:19:06
【问题描述】:

我在 Aginity Workbench 上使用 Netezza SQL 并拥有以下数据:

id           DATE1              DATE2
1            2013-07-27         NULL
2            NULL               NULL
3            NULL               2013-08-02
4            2013-09-10         2013-09-23
5            2013-12-11         NULL
6            NULL               2013-12-19

我需要将 DATE1 中的所有 NULL 值填入 DATE1 字段中已填写的前面值。对于 DATE2,我需要执行相同操作,但顺序相反。所以我想要的输出如下:

id           DATE1              DATE2
1            2013-07-27         2013-08-02
2            2013-07-27         2013-08-02
3            2013-07-27         2013-08-02
4            2013-09-10         2013-09-23
5            2013-12-11         2013-12-19
6            2013-12-11         2013-12-19

我只有数据的读取权限。所以创建表格或视图是不可能的

【问题讨论】:

  • 是否有任何类型的 id 列建立顺序?鉴于您希望第 2 行(仅包含您提供的列中的空值)清楚地位于第 1 行和第 3 行之间,因此必须至少有一个其他列可以确定该列。数据库表不是有序集。

标签: apache-spark hive hql


【解决方案1】:

this怎么样?

select
  id
  ,last_value(date1 ignore nulls) over (
    order by id
    rows between unbounded preceding and current row
  ) date1
  ,first_value(date2 ignore nulls) over (
    order by id
    rows between current row and unbounded following
  ) date2

您也可以手动计算,而不是依赖窗口函数。

with chain as (
  select 
    this.*,
    prev.date1 prev_date1,
    case when prev.date1 is not null then abs(this.id - prev.id) else null end prev_distance,
    next.date2 next_date2,
    case when next.date2 is not null then abs(this.id - next.id) else null end next_distance
  from 
    Table1 this 
    left outer join Table1 prev on this.id >= prev.id
    left outer join Table1 next on this.id <= next.id
), min_distance as (
  select
    id,
    min(prev_distance) min_prev_distance,
    min(next_distance) min_next_distance
  from
    chain
  group by
    id
)
select
  chain.id,
  chain.prev_date1,
  chain.next_date2
from
  chain
  join min_distance on 
    min_distance.id = chain.id
    and chain.prev_distance = min_distance.min_prev_distance
    and chain.next_distance = min_distance.min_next_distance
order by chain.id

如果您无法通过减法计算 ID 之间的距离,只需将排序方案替换为 row_number() 调用即可。

【讨论】:

  • 虽然@FuzzyTree 提供的自联接答案会产生相同的结果,但我想您会发现 jeremytwfortune 提供的窗口聚合解决方案可能要快几个数量级,因为它只涉及一个 sn- p,并且不依赖基于表达式的连接,这将导致表的广播。另一方面,窗口聚合更多地依赖于主机处理,因为没有 PARTITION BY 子句。试一试,看看哪个更适合你。如果我是赌徒,我会选择 Jeremy's。
  • 谢谢,@ScottMcG。不过,我不完全确定@FuzzyTree 的解决方案是否确实给出了相同的答案。如果您将 ID 3 编辑为低于 ID 1 的日期,则来自 ID 1 的日期将出现在 ID 3 的行上。这是因为使用的聚合是 minmax,而不是 first_valuelast_value .
  • 噢!我懒得看那个了。
  • @ScottMcG - 这个窗口 agg 在我的 Netezza 上给出了 ERROR: 614057 : Partition rowcount limit exceeded,有一个 400 万行的表,使用较小的测试数据它可以正常工作 - 有什么想法吗?
  • 如果您的数据太大而无法使用,我更新了删除窗口函数的答案。
【解决方案2】:

我认为 Netezza 支持 max()min()order by 子句。所以,你可以这样做:

select max(date1) over (order by date1) as date1,
       min(date2) over (order by date2 desc) as date2
 . . .

编辑:

在 Netezza 中,您可以使用 last_value()first_value() 来执行此操作:

select last_value(date1 ignore nulls) over (order by id rows between unbounded preceding and 1 preceding) as date1,
       first_value(date1 ignore nulls) over (order by id rows between 1 following and unbounded following) as date2

Netezza 似乎不支持IGNORE NULLs 上的LAG(),但它支持这些功能。

【讨论】:

  • 刚刚尝试过 - 它并不能完全解决我的问题。您将在示例中看到,当 Date1 有一个新值时,我希望它后面的 NULL 采用该新值。虽然如果我们使用 min() over() 甚至 first_value() over(),它会用全局最小值填充空值......不过感谢您的回答......我更新了我的问题以更清楚地说明什么我要
【解决方案3】:

我只在 Oracle 中对此进行了测试,因此希望它在 Netezza 中也能正常工作:

小提琴: http://www.sqlfiddle.com/#!4/7533f/1/0

select id,
       coalesce(date1, t1_date1, t2_date1) as date1,
       coalesce(date2, t3_date2, t4_date2) as date2
  from (select t.*,
               t1.date1 as t1_date1,
               t2.date1 as t2_date1,
               t3.date2 as t3_date2,
               t4.date2 as t4_date2,
               row_number() over(partition by t.id order by t.id) as rn
          from tbl t
          left join tbl t1
            on t1.id < t.id
           and t1.date1 is not null
          left join tbl t2
            on t2.id > t.id
           and t2.date1 is not null
          left join tbl t3
            on t3.id < t.id
           and t3.date2 is not null
          left join tbl t4
            on t4.id > t.id
           and t4.date2 is not null
         order by t.id) x
 where rn = 1

【讨论】:

    【解决方案4】:

    这是一种使用自联接使用最近的最小/最大非空日期填充 NULL 日期的方法。此查询应该适用于大多数数据库

    select t1.id, max(t2.date1), min(t3.date2)
    from tbl t1
    join tbl t2 on t1.id >= t2.id
    join tbl t3 on t1.id <= t3.id
    group by t1.id
    

    http://www.sqlfiddle.com/#!4/acc997/2

    【讨论】:

      猜你喜欢
      • 2021-09-23
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      • 2019-09-23
      • 1970-01-01
      • 2017-07-06
      • 2011-03-21
      • 1970-01-01
      相关资源
      最近更新 更多