我很难将存储过程从 SQL Server 转换为 Oracle,以使我们的产品与之兼容。
我有根据时间戳返回某些表的最新记录的查询:
SQL 服务器:
SELECT TOP 1 *
FROM RACEWAY_INPUT_LABO
ORDER BY t_stamp DESC
=> 这将返回我最近的记录
但是甲骨文:
SELECT *
FROM raceway_input_labo
WHERE rownum <= 1
ORDER BY t_stamp DESC
=>这将返回我最旧的记录(可能取决于索引),无论 ORDER BY
语句!
我以这种方式封装了 Oracle 查询以满足我的要求:
SELECT *
FROM
(SELECT *
FROM raceway_input_labo
ORDER BY t_stamp DESC)
WHERE rownum <= 1
它有效。但这对我来说听起来像是一个可怕的黑客攻击,特别是如果我在所涉及的表中有很多记录。
实现这一目标的最佳方法是什么?
where
语句在 order by
之前执行。因此,您想要的查询是“取第一行,然后按 t_stamp
desc排序”。这不是你想要的。
子查询方法是在 Oracle 中执行此操作的正确方法。
如果您想要一个在两个服务器上都可以使用的版本,您可以使用:
select ril.*
from (select ril.*, row_number() over (order by t_stamp desc) as seqnum
from raceway_input_labo ril
) ril
where seqnum = 1
外部 *
将在最后一列返回“1”。您需要单独列出这些列以避免这种情况。
请改用 ROW_NUMBER()
。 ROWNUM
是一个伪列,ROW_NUMBER()
是一个函数。您可以阅读它们之间的差异并查看以下查询的输出差异:
SELECT * FROM (SELECT rownum, deptno, ename
FROM scott.emp
ORDER BY deptno
)
WHERE rownum <= 3
/
ROWNUM DEPTNO ENAME
---------------------------
7 10 CLARK
14 10 MILLER
9 10 KING
SELECT * FROM
(
SELECT deptno, ename
, ROW_NUMBER() OVER (ORDER BY deptno) rno
FROM scott.emp
ORDER BY deptno
)
WHERE rno <= 3
/
DEPTNO ENAME RNO
-------------------------
10 CLARK 1
10 MILLER 2
10 KING 3
ROWNUM
可能比 ROW_NUMBER()
快,因此是否应该使用其中一个取决于许多因素。
从 Oracle 12c 开始,我们现在有 row limiting clauses 可以做到这一点。
SELECT *
FROM raceway_input_labo
ORDER BY t_stamp DESC
FETCH FIRST ROW ONLY
或者许多 alternatives 用于不同的场景(前 n 行、平局处理等)。
在上面的评论中记录了几个设计问题。简而言之,在 Oracle 中,当您有大型表和/或具有相同列名的表时,您需要手动限制结果(并且您不希望将它们全部显式键入并全部重命名)。简单的解决方案是找出你的断点并在你的查询中限制它。或者,如果您没有冲突的列名约束,您也可以在内部查询中执行此操作。例如
WHERE m_api_log.created_date BETWEEN TO_DATE('10/23/2015 05:00', 'MM/DD/YYYY HH24:MI')
AND TO_DATE('10/30/2015 23:59', 'MM/DD/YYYY HH24:MI')
将大大减少结果。然后你可以 ORDER BY 甚至做外部查询来限制行。
另外,我认为 TOAD 具有限制行数的功能;但是,不确定这是否会限制在 Oracle 上的实际查询中。没有把握。
在这个用例中我建议的替代方法是使用 MAX(t_stamp) 来获取最新的行......例如
select t.* from raceway_input_labo t
where t.t_stamp = (select max(t_stamp) from raceway_input_labo)
limit 1
我的编码模式偏好(也许) - 可靠,通常比尝试从排序列表中选择第一行执行或更好 - 而且意图更明确易读。希望这可以帮助 ...
SQLer
不定期副业成功案例分享
raceway_input_labo
表并分配行号,然后过滤吗?如果是这样,这不会导致大表出现问题吗?