sql - ORDER BY在PARTITION BY函数中的作用是什么?

标签 sql oracle sql-order-by partition-by

我有一个包含数据的表格,

    ID        SEQ    EFFDAT                 
------- ---------    -----------------------
  1024          1    01/07/2010 12:00:00 AM   
  1024          3    18/04/2017 12:00:00 AM   
  1024          2    01/08/2017 12:00:00 AM   

当我执行以下查询时,我得到了错误的最大序列,但我仍然得到了正确的最大生效日期。

询问:
SELECT 
max(seq) over (partition by id order by EFFDAT desc) maxEffSeq,
partitionByTest.*,
max(EFFDAT) over (partition by (id) order by EFFDAT desc ) maxeffdat
FROM partitionByTest;

输出:
 MAXEFFSEQ         ID        SEQ EFFDAT                   MAXEFFDAT              
---------- ---------- ---------- ------------------------ ------------------------
         2       1024          2 01/08/2017 12:00:00 AM   01/08/2017 12:00:00 AM   
         3       1024          3 18/04/2017 12:00:00 AM   01/08/2017 12:00:00 AM   
         3       1024          1 01/07/2010 12:00:00 AM   01/08/2017 12:00:00 AM 

如果我在查询中删除订单,我会得到正确的输出。

询问:
SELECT max(seq) over (partition by id ) maxEffSeq, partitionByTest.*,
max(EFFDAT) over (partition by (id) order by EFFDAT desc ) maxeffdat
FROM partitionByTest;

输出:
 MAXEFFSEQ         ID        SEQ EFFDAT                   MAXEFFDAT              
---------- ---------- ---------- ------------------------ ------------------------
         3       1024          2 01/08/2017 12:00:00 AM   01/08/2017 12:00:00 AM   
         3       1024          3 18/04/2017 12:00:00 AM   01/08/2017 12:00:00 AM   
         3       1024          1 01/07/2010 12:00:00 AM   01/08/2017 12:00:00 AM   

我知道当我们使用 MAX 函数时,不需要使用 order by 子句。但是我很想知道 order by 在按功能分区中是如何工作的,以及为什么当我使用 order by 子句时它会给出错误的序列结果和正确的日期结果?

最佳答案

添加 order by还暗示了一个窗口子句,并且由于您没有指定一个窗口子句,因此您将获得默认值,所以您实际上是在做:

max(seq) over (
  partition by id
  order by EFFDAT desc
  range between unbounded preceding and current row
)

如果您考虑以相同的方式对数据进行排序时数据的外观,按降序排列:
select partitionbytest.*,
  count(*) over (partition by id order by effdat desc) range_rows,
  max(seq) over (partition by id order by effdat desc) range_max_seq,
  count(*) over (partition by id) id_rows,
  max(seq) over (partition by id) id_max_seq
from partitionbytest
order by effdat desc;

        ID        SEQ EFFDAT     RANGE_ROWS RANGE_MAX_SEQ    ID_ROWS ID_MAX_SEQ
---------- ---------- ---------- ---------- ------------- ---------- ----------
      1024          2 2017-08-01          1             2          3          3
      1024          3 2017-04-18          2             3          3          3
      1024          1 2010-07-01          3             3          3          3

然后它变得更加清晰。我已经包含了等效的分析计数,因此您还可以查看正在考虑的行数,有和没有 order by条款。
  • 对于第一行,最大 seq 值是通过查看当前行的数据和所有具有较晚日期的前一行(因为它是降序的)找到的,并且没有这些,所以它是来自该行本身的值 - 所以它是 2 . 不考虑它后面的行,seq 值为 3 和 1。
  • 对于第二行,它查看当前行和所有具有较晚日期的前面的行,因此它可以同时考虑前面的值 2 和当前的值 3。因为 3 在这些中最高,所以它表明了这一点。不考虑它后面的 seq 值为 1 的行。
  • 对于第三行,它查看当前行和所有具有较晚日期的前面的行,因此它可以考虑前面的值 2 和 3 以及当前的值 1。由于 3 仍然是最高的,因此再次显示。

  • 没有 order by子句它总是考虑该 ID 的所有值,因此它认为 3 是所有值的最高值。

    the documentation for analytic functions有关如何确定的更多详细信息,特别是:

    The group of rows is called a window and is defined by the analytic_clause. For each row, a sliding window of rows is defined. The window determines the range of rows used to perform the calculations for the current row. Window sizes can be based on either a physical number of rows or a logical interval such as time.





    You cannot specify [windowing_clause] unless you have specified the order_by_clause.





    If you omit the windowing_clause entirely, then the default is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.

    关于sql - ORDER BY在PARTITION BY函数中的作用是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51761481/

    相关文章:

    sql - Oracle 程序与 MS 程序与 Oracle 程序包

    sql - 如何正确使用 Sql Server ROW_NUMBER 函数进行有序查询?

    sql - 如何使用简单的更新语句更新表中的 varray 类型?

    sql - SQL 分组的结果不符合预期

    sql - 排序查询结果太慢

    mysql - ORDER BY 是否会影响连接 View 中的性能?

    mysql - 注册用户和未注册用户

    oracle - 带时区的 hibernate 时间戳

    java - 在单个类中连接到两个不同的数据库

    sql - Oracle SQL 中的自定义顺序