窗口函数的确定性排序顺序

时间:2015-06-29 11:45:59

标签: sql postgresql sql-order-by greatest-n-per-group amazon-redshift

我有status表,我想获取最新的详细信息。

Slno |   ID | Status | date
  1  |   1  | Pass   | 15-06-2015 11:11:00 - this is inserted first
  2  |   1  | Fail   | 15-06-2015 11:11:00 - this is inserted second 
  3  |   2  | Fail   | 15-06-2015 12:11:11 - this is inserted first
  4  |   2  | Pass   | 15-06-2015 12:11:11 - this is inserted second

我使用带partition by ID order by date desc的窗口函数来获取第一个值 例外输出:

2  |   1  | Fail   | 15-06-2015 11:11:00 - this is inserted second
4  |   2  | Pass   | 15-06-2015 12:11:11 - this is inserted second

实际输出:

1  |   1  | Pass   | 15-06-2015 11:11:00 - this is inserted first
3  |   2  | Fail   | 15-06-2015 12:11:11 - this is inserted first

根据[http://docs.aws.amazon.com/redshift/latest/dg/r_Examples_order_by_WF.html],向窗口函数添加第二个ORDER BY列可以解决问题。但我没有任何其他专栏来区分行!
还有另一种方法可以解决这个问题吗?

编辑:为了清楚起见,我已在此处添加了slno。我在桌子上没有这样的slno

我的SQL:

with range as (
  select id from status where date between 01-06-2015 and 30-06-2015
), latest as ( 
  select status, id, row_number() OVER (PARTITION BY id ORDER BY date DESC) row_num
)
select * from latest where row_num = 1

1 个答案:

答案 0 :(得分:0)

如果您的表中没有slno,那么您没有任何可靠的信息,首先会插入哪一行。表中没有自然顺序,行的物理顺序可以随时更改(任何更新,或使用VACUUM等)。

可以使用 不可靠的 技巧:按内部ctid订购。

select *
from  (
   select id, status
        , row_number() OVER (PARTITION BY id
                             ORDER BY date, ctid) AS row_num
   from   status  -- that's your table name??
   where  date >= '2015-06-01'  -- assuming column is actually a date
   and    date <  '2015-07-01'
  ) sub
where  row_num = 1;
  • 如果没有任何其他信息首先出现哪一行(首先是设计错误,请修复它!),您可能会尝试保存使用内部{ {3}}

    最初插入时,行将按物理顺序排列,但随着对表格或VACUUM或其他事件的任何写入操作,行可以随时更改。
    这是最后的衡量标准,中断。

  • 您提出的查询在几个方面无效:第一个CTE中缺少列名,第二个CTE中缺少表名,...

  • 您不需要CTE。

使用DISTINCT ON更简单(ctid的注意事项同样适用):

SELECT DISTINCT ON (id)
       id, status
FROM   status
WHERE  date >= '2015-06-01'
AND    date <  '2015-07-01'
ORDER  BY id, date, ctid;