【问题标题】:How does order_by behave in sql when order_by column is having duplicate values?当 order_by 列具有重复值时,order_by 在 sql 中的行为如何?
【发布时间】:2019-06-19 08:32:10
【问题描述】:

我正在使用 sql 的“first_value”函数使用查询来填充空值 整个查询示例如下:

WITH example (date,close) AS 
(VALUES 
    ('12:00:00',3),
    ('12:00:01',4),
    ('12:00:01',5),
    ('12:00:03',NULL),
    ('12:00:04',NULL), 
    ('12:00:05',3)
)
SELECT * INTO temporary table market_summary FROM example;

select 
    date, 
    cccc, 
    first_value(cccc) over (partition by grp_close) as corrected_close
from (
      select date, close as cccc,
             sum(case when close is not null then 1 end) over (order by date) as grp_close
      from   market_summary
) t

结果是:


    date      cccc   corrected_close
1   12:00:00    3       3
2   12:00:01    4       4
3   12:00:01    5       4
4   12:00:03    NULL    4
5   12:00:04    NULL    4
6   12:00:05    3       3

在此示例中,“日期”用作查询中的 order_by 列,但它与“12:00:01”重复。空值用'4'填充,理想情况下是不正确的,因为我希望用以前的非空值填充空值,在这种情况下是'5'而不是'4',因此结果应该如下:


    date       cccc   corrected_close
1   12:00:00    3       3
2   12:00:01    4       4
3   12:00:01    5       5
4   12:00:03    NULL    5
5   12:00:04    NULL    5
6   12:00:05    3       3

如何修改查询以满足我的要求?

【问题讨论】:

  • 您使用的是 MySQL、Oracle 还是 Postgresql?
  • “当 order_by 列具有重复值时 order_by 在 sql 中的行为如何?” ANSI/ISO 标准 SQL 被定义为返回非唯一列的非确定性(随机)结果重复值的值。要始终获得 100% 确定性(固定),您还至少向 ORDER BY 子句添加一列,其中包含主键或唯一键。
  • 对于示例数据 1 | 12:00:00, 2 | 12:00:01, 3 | 12:00:01ORDER BY date 的含义,您不知道哪个记录将是第一个或最后一个,12:00:01 值这些记录的结果顺序是不确定的(随机) , 要获得非确定性(随机)结果,您必须使用 ORDER BY date, id 假设 id 是主键。
  • 你需要使用first_value(cccc) over (partition by grp_close order by date, cccc) as corrected_close -- 增加了Order by子句
  • for @jarlh im 使用 postgres

标签: sql postgresql sql-order-by


【解决方案1】:

您应该更改窗口函数以获得正确的值:

last_value(cccc) IGNORE NULLS OVER (PARTITION BY grp_close ORDER BY date)

这是SQL标准定义的方式,但是很多数据库并没有实现这方面的标准。由于您标记了很多数据库,因此很难给出适用于所有数据库的通用答案。

【讨论】:

    【解决方案2】:

    你想要的是lag( . . . ignore nulls)。但是,Postgres 不支持这一点。

    这是一种解决方法:

    select e.*, coalesce(close, max(close) over (partition by grp))
    from (select e.*, count(close) over (order by date) as grp
          from example e
         ) e;
    

    你甚至可以在没有子查询的情况下做到这一点:

    select e.*,
           coalesce(close,
                    (array_remove(array_agg(close) over (order by date), null))[array_upper(array_remove(array_agg(close) over (order by date), null), 1)]
                   )
    
    from example e;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-24
      • 2017-08-27
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-26
      • 2012-05-06
      相关资源
      最近更新 更多