【问题标题】:oracle dbms max returning all valuesoracle dbms max 返回所有值
【发布时间】:2017-02-22 12:37:41
【问题描述】:

我正在尝试在 Oracle Express Edition 数据库上运行以下查询。

SELECT SIGHTING_ID, MAX(DISTANCE)
FROM
(
    SELECT SIGHTING_ID,
          SQRT(POWER(LATITUDE + 28, 2) + POWER(LONGITUDE - 151, 2)) AS DISTANCE
    FROM SIGHTINGS
)
GROUP BY SIGHTING_ID;

查询的目的是返回距离坐标(-28, 151)最大距离的瞄准的 SIGHTING_ID 和 DISTANCE

SIGHTINGS表的描述如下

 desc SIGHTINGS
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 SIGHTING_ID                               NOT NULL NUMBER
 SPOTTER_ID                                         NUMBER
 BIRD_ID                                            NUMBER
 LATITUDE                                           NUMBER
 LONGITUDE                                          NUMBER
 SIGHTING_DATE                                      DATE
 DESCRIPTION                                        VARCHAR2(255)

当我运行查询而不是选择最大距离时,它会选择并显示整个目击事件列表及其各自的距离。 SIGHTINGS 有大量的元组,但下面是当前输出的一小部分列表

 SIGHTING_ID MAX(DISTANCE)
 ----------- -------------
 264172    2.01556444
 264174    2.34029913
 264180    2.87647354
 264198    .637887137
 264205    2.08568933
 264211    .232594067
 264215    2.34104677
 264221           .75
 264224    .148660687
 264235    .684470598

我的问题是如何使 MAX 聚合函数起作用,以便它只返回最大距离和尊重 SIGHTING_ID?

【问题讨论】:

    标签: sql oracle select max aggregate-functions


    【解决方案1】:

    使用 Oracle 的rownum

    SELECT * FROM 
        (SELECT SIGHTING_ID, SQRT(POWER(LATITUDE + 28, 2) + POWER(LONGITUDE - 151, 2)) AS DISTANCE
         FROM SIGHTINGS
         ORDER BY distance DESC)
    WHERE ROWNUM = 1
    

    您获得每个SIGHTING_ID 的记录的原因是您按它进行分组。按子句分组意味着 -> 为子句中提到的列的每个组合提供 1 条记录。

    【讨论】:

    • 如果有两条记录的最大距离在这种情况下,它将跳过其中一条记录。
    • 你怎么知道这不是他想要的? @hemalp108
    • 我对你的回答毫无疑问,让他决定他想要什么。我只是出于好奇而问它。
    • 非常感谢,去掉多余的支架后效果很好
    • @FrankSchmitt - 你又是对的。咖啡还不够!
    【解决方案2】:

    在 Oracle 12c+ 中,您可以使用 ANSI 标准功能:

    SELECT SIGHTING_ID,
          SQRT(POWER(LATITUDE + 28, 2) + POWER(LONGITUDE - 151, 2)) AS DISTANCE
    FROM SIGHTINGS
    ORDER BY distance DESC
    FETCH FIRST 1 ROW ONLY;
    

    在早期版本中,@sagi 的解决方案可能是最好的方法。

    【讨论】:

    • 此类问题的正确解决方案是第一个/最后一个聚合函数(正如我在回答中所展示的那样)。 docs.oracle.com/cd/B19306_01/server.102/b14200/functions056.htm
    • @mathguy 您的措辞具有误导性。您的方法是几种正确解决方案之一 - Gordon Linoff 的方法是另一种方法,而 sagi 的方法又是另一种方法。
    • @FrankSchmitt - 你是对的,我应该说“最好”,而不是“正确”。对于 Oracle 12c,Gordon 的解决方案同样出色;我不同意他对早期版本的评估。我会编辑我的 cmets,但在 SO 上这是不可能的。
    • @mathguy 。 . .我更喜欢 Sagi 的解决方案,因为它更容易推广到多列(或一行中的所有列)。
    【解决方案3】:
    select min(sighting_id) keep (dense_rank first order by distance) as sighting_id,
           min(distance)                                              as distance
    from sightings;
    

    这将找到具有最短distance 的一行或多行,并从这些行(并且仅这些行)中,如果存在平局(最短的distance 由两个或多个sighting id 实现),它选择具有最小sighting_id 的那个。相反,如果您想要最大的latitude(比如说),仍然是最短的distance,请将order by distance 更改为order by distance, latitude desc。其他组合的处理方式相同。

    【讨论】:

      猜你喜欢
      • 2012-11-30
      • 1970-01-01
      • 2017-03-20
      • 2015-06-02
      • 2018-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多