我在Oracle上,我需要在一个请求中同时使用ORDER BY
和ROWNUM
。我需要对我的内部查询进行双重嵌套,因为我想首先应用ORDER BY
,然后选择<{1}} 。
我的数据在最高级别由ROWNUM=1
过滤。但是,我在内部查询中收到错误,因为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!
查询的WHERE
子句中进行过滤。但这当然很慢,因为内部SQL在没有过滤的情况下返回整个数据。
SELECT
如何将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
的效果。
我的最终解决方案正如Kim Berg Hansen所建议并由轮辋改进:
(我不得不使用ROWNUM
而不是MIN()
MAX()
答案 0 :(得分:2)
在您使用的标量子查询中,您只能引用&#34; main&#34;中的表格。查询&#34;一个嵌套级别&#34;,而不是任何进一步向下,如您所见。 (我相信这个限制在版本12中解除了,所以也许你可以升级你的数据库?; - )
在标量子查询中,您尝试根据您的顺序获取第一行的INSERTDATE列的值。这也可以在没有嵌套的情况下编写如下:
SELECT
O.INSERTDATE OrderCreateDate,
-- Determine delivery date
(SELECT MAX(DD.INSERTDATE) KEEP (
DENSE_RANK FIRST ORDER BY
DD.CLOSED ASC, ABS(TRUNC(CURRENT_DATE-TO_DATE(TO_CHAR(DD.INSERTDATE, 'DDMMYYYY'), 'DDMMYYYY'))) 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 -- This will no longer give "Invalid identifier O.ID"
DD.DELFLAG IS NULL AND OP2.DELFLAG IS NULL
) DeliveryDate
FROM MY_ORDER_TABLE O
WHERE O.ID = 620; -- ID goes here!
KEEP(DENSE_RANK FIRST告诉MAX函数,它应该在ORDER BY子句中计算那些排在 first 的行的
(如果您使用的是Oracle版本12,则替代KEEP(DENSE_RANK技巧将使用SELECT语句的FIRST 1 ROW ONLY子句。)