从列中选择最大的邮政编码

时间:2015-01-07 13:01:24

标签: sql oracle greatest-n-per-group

我想获得DB中最大的邮政编码。通常我会这样做

SELECT * 
FROM (
   Select * From tbuser ORDER BY zip DESC
) 
WHERE rownum = 1

使用此代码,我可以获得最大的邮政编码值,而不会有重复的行(因为邮政编码不是主键)。

但日本的主要公司说我无法使用它,因为当连接速度很慢或者数据库有非常大的数据时,你无法获得正确的行。如果有人可以提供帮助,对我来说将是一个很大的帮助。

8 个答案:

答案 0 :(得分:8)

  

我想获得DB中最大的邮政编码。

如果您确实只想要邮政编码,请尝试:

SELECT MAX(zip) FROM TBUSER;

这将使用zip列上的索引(如果存在)。

话虽这么说,Oracle通常足够聪明,可以使用ROWNUM正确优化子查询选择。也许你的主要公司更关心子查询中可能的“全表”ORDER BY`? OTH,如果问题实际上是“慢速网络”,如果您的方法确实导致“过度的带宽消耗”,那么使用网络分析仪或其他工具可能需要花一些时间让您的DBA查看线路。我真诚地怀疑......


如果你想检索具有最大邮政编码的整行,这里的an other answer略有不同(在我看来,这是使用NATURAL JOIN的罕见情况之一):< / p>

select * from t
natural join (select max(zip) zip from t);

当然,如果是重复项,这将返回多行。您必须将其与其他各种答案中发布的几个选项之一相结合,才能返回1行。

作为一个额外的解决方案,并且由于您不允许使用ROWNUM(并假设row_number也是任意禁止的),您可以使用以下设计的方式实现所需的结果:

select * from t
where rowid = (
  select min(t.rowid) rid from t
  natural join (select max(zip) zip from t)
);

请参阅http://sqlfiddle.com/#!4/3bd63/5

但老实说,没有任何严肃的理由希望这样的查询比简单的... ORDER BY something DESC) WHERE rownum <= 1查询表现更好。

答案 1 :(得分:3)

这听起来像是一个新手数据库管理员的坏建议(伪装成规则),他不了解他在看什么。但是,这种洞察力对你没有帮助。很少以“你是一个阻碍无能的人”开始的对话能够实现任何目标。

所以,这就是事情。首先,您需要确保zip列上有索引。它不一定是主键。

其次,您可以尝试解释Oracle的表服务器实际上是否优化了... ORDER BY something DESC) WHERE rownum <= 1查询样式。他们的服务器做得很好。你的用例很常见。

但是,如果这对您的DBA不起作用,请尝试说“我听到了你”并执行此操作。

SELECT * FROM (
    SELECT a.* 
      FROM ( SELECT MAX(zip) zip FROM zip ) b
      JOIN ZIP a ON (a.zip = b.zip)
 ) WHERE rownum <= 1

这将获得一行具有最高编号zip值但没有ORDER BY,而您的DBA错误地认为这会弄乱他的服务器的RAM池。而且,它的效率相当高。只要zip有索引。

答案 2 :(得分:3)

当你正在寻找一种方法来获得没有rownum的所需记录时,......

...以下是从Oracle 12c开始的方法:

select * 
from tbuser
order by zip desc fetch first 1 row only;

...以下是Oracle 12c之前的操作方法:

select * 
from (select tbuser.*, row_number() over(order by zip desc) as rn from tbuser)
where rn = 1;
编辑:正如Sylvain Leroux所指出的那样,dbms对所有记录进行排序而不仅仅是找到最大记录的工作量更大。这是一个没有rownum的最大查询:

select * 
from tbuser where rowid =
(select max(rowid) keep (dense_rank last order by zip) from tbuser);

但正如Sylvain Leroux所提到的那样,该列上是否有索引也有所不同。我做过的一些测试表明,对于列上的索引,分析函数比传统函数慢。您的原始查询只会进入索引,转到最高值,选择记录然后停止。你不会更快地得到这个。我上次提到的查询在非索引列上非常快,在索引列上比你的慢。

答案 3 :(得分:2)

您的要求似乎是随意的,但这应该会为您提供您所要求的结果。

SELECT * 
FROM (SELECT * FROM tbuser 
      WHERE zip = (SELECT MAX(zip) FROM tbuser)) 
WHERE rownum = 1

答案 4 :(得分:2)

好的 - 尝试这样的事情:

SELECT *
  FROM TBUSER
  WHERE ZIP = (SELECT MAX(ZIP) FROM TBUSER);

根据上述语句从游标中获取单行,然后关闭游标。如果你正在使用PL / SQL,你可以这样做:

FOR aRow IN (SELECT *
               FROM TBUSER
               WHERE ZIP = (SELECT MAX(ZIP) FROM TBUSER))
LOOP
   -- Do something with aRow

   -- then force an exit from the loop

   EXIT;
END LOOP;

分享并享受。

答案 5 :(得分:1)

我想知道还没有人发布这个答案。我认为这就是方法,你应该这样做。

SELECT * 
FROM (
   Select a.*, max(zip) over () max_zip
   From tbuser a
) 
WHERE zip=max_zip
and rownum = 1

答案 6 :(得分:1)

您的查询只获得具有最大邮政编码的所有记录中的一个随机行。因此,使用其他邮政编码或多个记录或零记录检索记录不是问题(只要表中至少有一条记录)。

也许日本只是期望其中一行包含该邮政编码?然后,您可能只需添加另一个订单条件即可获得该特定的所需行。

另一个想法:由于他们谈论的连接速度较慢,也可能是他们在一个会话中输入新的最大邮政编码,与另一个会话查询并获取旧的最大邮政编码,因为另一个会话的插入声明没有还没去过。但是,这就是当然这样做的方式。

BTW:选择最大邮政编码很奇怪。我想这只是一个例子来说明这个问题?

答案 7 :(得分:0)

如果您使用MAX函数获取多个记录(这是不可能的,但在您的情况下,您将获得,我不知道如何发布屏幕截图)然后您可以在您的SQL查询中使用DISTINCT获取单个记录

SELECT DISTINCT MAX(zipcode) FROM TableUSER

SQL FIDDLE