如何在没有subselect的情况下使用order by和rownum?

时间:2014-10-08 16:06:00

标签: sql oracle sql-order-by rownum

我需要使用order by和rownum构建一个查询,但不使用sublect。 需要获取有序查询的第一行。

换句话说,我想要

的结果
select * from (
SELECT CAMP1,ORDERCAMP
FROM TABLENAME
ORDER BY ORDERCAMP) where rownum=1;

不使用子选择。有可能吗?

我有一个Oracle 11.你可以说这是我的整个查询:

SELECT T1.CAMP_ID,
  T2.CAMP
  (SELECT OT.CAMP
  FROM OTHERTABLE OT
  WHERE OT.FK_TO_TABLE1=T1.CAMP_ID
  ORDER BY OT.ORDERCAMP
  )
FROM TABLE1 T1,
  TABLE2 T2
WHERE T1.FK_TO_T2=T2.PK;

子查询返回多行,我不能使用另一个子查询,如

SELECT T1.CAMP_ID,
  T2.CAMP
  (SELECT *
  FROM
    (SELECT OT.CAMP
    FROM OTHERTABLE OT
    WHERE OT.FK_TO_TABLE1=T1.CAMP_ID
    ORDER BY OT.ORDERCAMP
    )
  WHERE ROWNUM=1
  )
FROM TABLE1 T1,
  TABLE2 T2
WHERE T1.FK_TO_T2=T2.PK;
SELECT CAMP1,ORDERCAMP FROM TABLE2 ORDER BY ORDERCAMP

因为T1.CAMP_ID是第三级子查询中的无效标识符。

我希望我已经足够解释了自己。

3 个答案:

答案 0 :(得分:3)

您当前的查询(没有无效的ORDER BY)获得ORA-01427: single-row subquery returns more than one row。您可以嵌套子查询,但加入时只能返回一个级别;所以如果你这样做了:

SELECT T1.CAMP_ID, T2.CAMP,
  (SELECT CAMP FROM
  FROM
    (SELECT OT.CAMP
    FROM OTHERTABLE OT
    WHERE OT.FK_TO_TABLE1=T1.CAMP_ID
    ORDER BY OT.ORDERCAMP
    )
  WHERE ROWNUM = 1)
FROM TABLE1 T1, TABLE2 T2 WHERE T1.FK_TO_T2=T2.PK;

...然后你会得到ORA-00904: "T1"."CAMP_ID": invalid identifier。因此,大概是你的问题。

你可以做的是加入到第三个表,并使用分析ROW_NUMBER()函数来分配行号,然后使用围绕整个事物的外部选择来仅查找具有最低值的记录ORDERCAMP

SELECT CAMP_ID, CAMP, OT_CAMP
FROM (
  SELECT T1.CAMP_ID, T2.CAMP, OT.CAMP AS OT_CAMP,
    ROW_NUMBER() OVER (PARTITION BY T1.CAMP_ID ORDER BY OT.ORDERCAMP) AS RN
  FROM TABLE2 T2
  JOIN TABLE1 T1 ON T1.FK_TO_T2=T2.PK
  JOIN OTHERTABLE OT ON OT.FK_TO_TABLE1=T1.CAMP_ID
)
WHERE RN = 1;

ROW_NUMBER()可以对T1.CAMP_ID主键值或其他任何唯一值进行分区。

SQL Fiddle demo,包括内部查询自行运行,以便您可以看到在应用外部过滤器之前分配的RN个数字。

另一种方法是使用汇总KEEP DENSE_RANK FIRST function

SELECT T1.CAMP_ID, T2.CAMP,
  MAX(OT.CAMP) KEEP (DENSE_RANK FIRST ORDER BY OT.ORDERCAMP) AS OT_CAMP
FROM TABLE2 T2
JOIN TABLE1 T1 ON T1.FK_TO_T2=T2.PK
JOIN OTHERTABLE OT ON OT.FK_TO_TABLE1=T1.CAMP_ID
GROUP BY T1.CAMP_ID, T2.CAMP;

哪个更短,不需要内部查询。我不确定一个人是否有任何真正的优势。

SQL Fiddle demo

答案 1 :(得分:1)

在最新版本的Oracle中,您可以执行以下操作:

SELECT CAMP1, ORDERCAMP
FROM TABLENAME
ORDER BY ORDERCAMP
FETCH FIRST 1 ROWS ONLY;

否则,我认为你需要某种子查询。

答案 2 :(得分:-2)

您可以使用LIMIT或SELECT TOP 1 SELECT CAMP1, ORDERCAMP FROM TABLENAME ORDER BY ORDERCAMP LIMIT 1