我想获得DB中最大的邮政编码。通常我会这样做
SELECT *
FROM (
Select * From tbuser ORDER BY zip DESC
)
WHERE rownum = 1
使用此代码,我可以获得最大的邮政编码值,而不会有重复的行(因为邮政编码不是主键)。
但日本的主要公司说我无法使用它,因为当连接速度很慢或者数据库有非常大的数据时,你无法获得正确的行。如果有人可以提供帮助,对我来说将是一个很大的帮助。
答案 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