我在Oracle上,我需要在一个请求中同时使用ORDER BY
和ROWNUM
。我需要双重嵌入我的内部查询,因为我想申请ORDER BY
第一个并选择ROWNUM=1
然后。使用ORDER BY和ROWNUM的双重嵌套查询中的标识符无效
我的数据最多可以经由O.ID
进行过滤。但是,我在我的内部查询中遇到错误,因为O.ID
在那里是未知标识。
我想要什么:
SELECT
O.INSERTDATE OrderCreateDate,
-- Determine delivery date
(SELECT INSERTDATE FROM (
SELECT OP2.FK_ORDER, DD.ID, DD.INSERTDATE FROM MY_DELIVERYDATE_TABLE DD
JOIN MY_ORDERPOS_TABLE OP2 ON DD.FK_ORDERPOS=OP2.ID
LEFT OUTER JOIN MY_ORDER_TABLE O2 ON OP2.FK_ORDER=O2.ID
WHERE OP2.FK_ORDER=O.ID AND -- This gives me "Invalid identifier O.ID"
DD.DELFLAG IS NULL AND OP2.DELFLAG IS NULL
ORDER BY DD.CLOSED ASC, ABS(TRUNC(CURRENT_DATE-TO_DATE(TO_CHAR(DD.INSERTDATE, 'DDMMYYYY'), 'DDMMYYYY'))) ASC
) WHERE ROWNUM=1) DeliveryDate
FROM MY_ORDER_TABLE O
WHERE O.ID = 620; -- ID goes here!
我得到这个工作的唯一办法,就是当我在中间SELECT
查询WHERE
子句中进行筛选。但是这当然很慢,因为内部SQL返回整个数据而没有过滤。
SELECT
O.INSERTDATE OrderCreateDate,
-- Determine delivery date
(SELECT INSERTDATE FROM (
SELECT OP2.FK_ORDER, DD.ID, DD.INSERTDATE FROM MY_DELIVERYDATE_TABLE DD
JOIN MY_ORDERPOS_TABLE OP2 ON DD.FK_ORDERPOS=OP2.ID
LEFT OUTER JOIN MY_ORDER_TABLE O2 ON OP2.FK_ORDER=O2.ID
WHERE DD.DELFLAG IS NULL AND OP2.DELFLAG IS NULL
ORDER BY DD.CLOSED ASC, ABS(TRUNC(CURRENT_DATE-TO_DATE(TO_CHAR(DD.INSERTDATE, 'DDMMYYYY'), 'DDMMYYYY'))) ASC
) WHERE ROWNUM=1 AND FK_ORDER=O.ID) DeliveryDate -- Filtering here
FROM MY_ORDER_TABLE O
WHERE O.ID = 620;
如何传递O.ID
到内部查询或这怎么能查询被重新设计,仍保持ORDER BY
和ROWNUM
工作。
我的最终解决方案由金伯格汉森的建议,并通过轮辋改进:
(我不得不使用MIN()
代替MAX()
,虽然)
SELECT
O.INSERTDATE OrderCreateDate,
-- Determine delivery date
(SELECT MIN(DD.INSERTDATE) KEEP (DENSE_RANK FIRST ORDER BY
DD.CLOSED ASC, ABS(TRUNC(CURRENT_DATE-TRUNC(DD.INSERTDATE))) ASC)
FROM MY_DELIVERYDATE_TABLE DD
JOIN MY_ORDERPOS_TABLE OP2 ON DD.FK_ORDERPOS=OP2.ID
LEFT OUTER JOIN MY_ORDER_TABLE O2 ON OP2.FK_ORDER=O2.ID
WHERE OP2.FK_ORDER=O.ID AND
DD.DELFLAG IS NULL AND OP2.DELFLAG IS NULL
) DeliveryDate
FROM MY_ORDER_TABLE O
WHERE O.ID = 620; -- ID goes here!
这些是大型查询。相关部分并不完全突出。查看是否可以过滤出无关紧要的内容并发布可重现此问题的简单示例 – Andomar 2014-09-02 06:14:25
与问题无关,但可以通过使用[TRUNC(date)](http://docs.oracle.com/)来简化/改进查询cd/B28359_01/server.111/b28286/functions209.htm)从日期时间中删除时间部分。更改:'TO_DATE(TO_CHAR(DD.INSERTDATE,'DDMMYYYY','DDMMYYYY')''TRUNC(DD.INSERTDATE)' – Rimas 2014-09-02 07:34:35
@rims:谢谢你指出。 – user1438038 2014-09-02 20:45:11