当前位置: 首页 > 面试题库 >

Oracle MIN作为分析函数-ORDER BY的异常行为?

傅高逸
2023-03-14
问题内容

这个特殊情况是从一个示例中提炼出来的,在该示例中,程序员假定两次装罐车,首先要装载1号线。我更正了此问题,以允许以任何顺序执行加载-
但是,我发现在Oracle中MIN() OVER (PARTITION BY)允许使用a ORDER BY(在SQL
Server中不允许这样做),此外,它更改了函数的行为,导致ORDER BY显然是已添加到中PARTITION BY

WITH data AS (
SELECT 1 AS SHIPMENT_ID, 1 AS LINE_NUMBER, 2 AS TARE, 3 AS GROSS FROM DUAL
UNION ALL
SELECT 1 AS SHIPMENT_ID, 2 AS LINE_NUMBER, 1 AS TARE, 2 AS GROSS FROM DUAL
)
SELECT MIN(tare) OVER (PARTITION BY shipment_id) first_tare
,MAX(gross) OVER (PARTITION BY shipment_id) last_gross
,FIRST_VALUE(tare) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER) first_tare_incorrect
,FIRST_VALUE(gross) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER DESC) last_gross_incorrect
,MIN(tare) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER) first_tare_incorrect_still
,MAX(gross) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER DESC) last_gross_incorrect_still
,MIN(tare) OVER (PARTITION BY shipment_id, LINE_NUMBER) first_tare_incorrect_still2
,MAX(gross) OVER (PARTITION BY shipment_id, LINE_NUMBER) last_gross_incorrect_still2
 FROM data

一个SQL Server示例(注释掉了不适用的代码):

WITH data AS (
SELECT 1 AS SHIPMENT_ID, 1 AS LINE_NUMBER, 2 AS TARE, 3 AS GROSS -- FROM DUAL
UNION ALL
SELECT 1 AS SHIPMENT_ID, 2 AS LINE_NUMBER, 1 AS TARE, 2 AS GROSS -- FROM DUAL
)
SELECT MIN(tare) OVER (PARTITION BY shipment_id) first_tare
,MAX(gross) OVER (PARTITION BY shipment_id) last_gross
-- ,FIRST_VALUE(tare) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER) first_tare_incorrect
-- ,FIRST_VALUE(gross) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER DESC) last_gross_incorrect
-- ,MIN(tare) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER) first_tare_incorrect_still
-- ,MAX(gross) OVER (PARTITION BY shipment_id ORDER BY LINE_NUMBER DESC) last_gross_incorrect_still
,MIN(tare) OVER (PARTITION BY shipment_id, LINE_NUMBER) first_tare_incorrect_still2
,MAX(gross) OVER (PARTITION BY shipment_id, LINE_NUMBER) last_gross_incorrect_still2
 FROM data

那么问题来了:Oracle在做什么?为什么,对吗?


问题答案:

如果ORDER BYMIN分析函数中添加,则将其变为“到目前为止的最小”函数,而不是总的最小值。对于您要进行分区的最后一行,结果将是相同的。但是,前面的行可能有一个不同于整体最小值的“到目前为止”。

以该EMP表为例,您可以看到到目前为止该部门的最低工资最终收敛于该部门的整体最低工资。您会看到,任何给定部门的“到目前为止”的最小值都会随着遇到更低的值而减小。

SQL> ed
Wrote file afiedt.buf

  1  select ename,
  2         deptno,
  3         sal,
  4         min(sal) over (partition by deptno order by ename) min_so_far,
  5         min(sal) over (partition by deptno) min_overall
  6    from emp
  7*  order by deptno, ename
SQL> /

ENAME          DEPTNO        SAL MIN_SO_FAR MIN_OVERALL
---------- ---------- ---------- ---------- -----------
CLARK              10       2450       2450        1300
KING               10       5000       2450        1300
MILLER             10       1300       1300        1300
ADAMS              20       1110       1110         800
FORD               20       3000       1110         800
JONES              20       2975       1110         800
SCOTT              20       3000       1110         800
smith              20        800        800         800
ALLEN              30       1600       1600         950
BLAKE              30       2850       1600         950
MARTIN             30       1250       1250         950
SM0                30        950        950         950
TURNER             30       1500        950         950
WARD               30       1250        950         950
BAR
PAV

16 rows selected.

当然,当您尝试进行诸如计算个人最佳成绩之类的事情以供将来比较时,使用这种形式的分析函数会更有意义。如果您要跟踪某人的高尔夫得分,英里数或体重的下降,则显示个人最佳成绩可能是一种激励。

SQL> ed
Wrote file afiedt.buf

  1  with golf_scores as
  2  (  select 1 golfer_id, 80 score, sysdate dt from dual union all
  3     select 1, 82, sysdate+1 dt from dual union all
  4     select 1, 72, sysdate+2 dt from dual union all
  5     select 1, 75, sysdate+3 dt from dual union all
  6     select 1, 71, sysdate+4 dt from dual union all
  7     select 2, 74, sysdate from dual )
  8  select golfer_id,
  9         score,
 10         dt,
 11         (case when score=personal_best
 12               then 'New personal best'
 13               else null
 14           end) msg
 15    from (
 16  select golfer_id,
 17         score,
 18         dt,
 19         min(score) over (partition by golfer_id
 20                              order by dt) personal_best
 21    from golf_scores
 22*        )
SQL> /

 GOLFER_ID      SCORE DT        MSG
---------- ---------- --------- -----------------
         1         80 12-SEP-11 New personal best
         1         82 13-SEP-11
         1         72 14-SEP-11 New personal best
         1         75 15-SEP-11
         1         71 16-SEP-11 New personal best
         2         74 12-SEP-11 New personal best

6 rows selected.


 类似资料:
  • 问题内容: 执行以下代码片段时,这些代码片段主要来自Go的时间包文档及其Parse函数示例: 然后,您可以在控制台中获得正确的结果。 但是,当你改变值略有下降,例如,或者,它甚至没有定期输出错误的结果,并且输出看起来,如,或。 那么,为什么函数的行为如此奇怪?我该如何处理呢?每次使用该函数时,都应始终将layout变量定义为吗? 谢谢。 问题答案: 的和功能使用的数字在布局参数来标识哪个日期分量称

  • 运行lambda函数时,我得到一个Boto3无效参数异常。我正试图找到一种方法来处理这个异常。 我遇到了以下解决方案: 我使用的是python3,我知道boto现在已被弃用,并被boto3取代。但我在boto3中找不到等效的解决方案。 有人能帮我解决这个问题吗?

  • 首先要处理前面已经提到但还没有完全解决的问题。构造函数中发现错误时会发生什么情况? 例如,String 构造函数在 new 失败和无法取得保持 String 的内部表示所需空间时如何响应?问题是构造函数无法返回数值,如何让外部知道对象没有顺利构造呢,一种方案是返回没有正确构造的对象,希望对象使用者通过相应测试确定该对象是不能使用的对象。另一种方案是在构造函数之外设置一些变量。抛出的异常向外部传递失

  • 问题内容: 我已经找到了一种使代码按我希望的方式运行的方法,但是我想了解为什么它如此运行,以便提高对Go并发性的理解。 我正在测试以等待一些goroutine完成,因为我计划以这种方式多次上传到Amazon S3。 这是我最初的代码: 我很惊讶地看到输出是:。 取而代之的是这样的:。 由于循环甚至没有达到6,这对我来说毫无意义。后来我将该变量作为参数传递给匿名函数,然后按预期运行。 为什么会这样?

  • 问题内容: 当运行上述代码片段时,在控制台中,我得到的输出为: 但我期望输出为 但是当在main()内部更改如下所述的逻辑时 我正在获得所需的输出 根据我的理解,TreeMap的entrySet()方法返回地图中包含的映射的集合视图。集合的迭代器以升序键顺序返回映射。那么,为什么在第一种情况下会发生这种情况? 任何建议都将受到高度赞赏。 问题答案: 因为在字典上小于。 这里有一个提示: 这是另一个

  • 本文向大家介绍java异常机制分析,包括了java异常机制分析的使用技巧和注意事项,需要的朋友参考一下 本文实例分析了Java的异常机制,分享给大家供大家参考。相信有助于大家提高大家Java程序异常处理能力。具体分析如下: 众所周知,java中的异常(Exception)机制很重要,程序难免会出错,异常机制可以捕获程序中的错误,用来提高程序的稳定性和健壮性。 java中的异常分为Checked E