我有下表的订单。 orderId
是主键,parentOrderId
是表示此订单是否具有父订单的列。
例如:1,2,3,4没有母订单。 5,6,7,8有父订单。
+--------------------+----------------------+
| order_id | parent_order_id |
+--------------------+----------------------+
| 1 | null|
| 2 | null|
| 3 | null|
| 4 | null|
| 5 | 1 |
| 6 | 2 |
| 7 | 3 |
| 8 | 3 |
+--------------------+----------------------+
I need to query all Parents with no children or if there are children only get the latest child.
The result I need is : 4,5,6,8
4 because it has no children and should be returned.
5 because it is the only child of 1.
6 because that is the only child of 2.
8 because 3 has 2 children(7,8) and I need to return latest child. Pick max of orderId's.
我尝试过的事情:
SELECT
MAX(order_id)
FROM
orders
WHERE
parent_order_id IS NOT NULL
GROUP BY
parent_order_id
UNION ALL
SELECT
order_id
FROM
orders
WHERE
parent_order_id IS NULL
MINUS
SELECT
parent_order_id
FROM
orders;
我正在寻找什么:
上面的查询返回4,5,6,8。问题是我正在将此查询输入IN子句,并且oracle对于IN子句有1000个限制。我试图看看是否有更好的方法使用联接来解决此问题。 更新: 联接将帮助我检索订单表中的所有列,而不仅仅是id,为简单起见,我仅包括两列,表中还有更多列。现在,我正在获取id的第一个并将其输入子句中的另一个查询中,以获取与这些id匹配的所有列。
我还在寻找非特定于供应商的sql。
谢谢您的帮助。
答案 0 :(得分:1)
这里是使用connect by
查询(实际上是一种联接形式-针对像您这样的分层数据进行了优化)的一种解决此问题的方法。 WITH子句不是解决方案的一部分,它仅用于模拟您的输入。使用实际的表名和列名。
请注意,我在结果中也得到带有order_id = 5
的行(我在评论中问过这一点,您回答了其他问题,但不是这个问题)。
这显示了如何一次性获得所需的所有列。
with
orders_table (order_id, parent_order_id) as (
select 1, null from dual union all
select 2, null from dual union all
select 3, null from dual union all
select 4, null from dual union all
select 5, 1 from dual union all
select 6, 2 from dual union all
select 7, 3 from dual union all
select 8, 3 from dual
)
select order_id, parent_order_id
from (
select o.*
, max(order_id)
over (partition by connect_by_root order_id) as max_id
from orders_table o
where connect_by_isleaf = 1
start with parent_order_id is null
connect by parent_order_id = prior order_id
)
where order_id = max_id
;
ORDER_ID PARENT_ORDER_ID
-------- ---------------
5 1
6 2
8 3
4
答案 1 :(得分:1)
OP在对我的其他答案的评论中解释说,他需要一个尽可能使用标准SQL功能的查询。这样就排除了connect by
查询,也排除了nvl()
这样简单的功能。
下面的查询得到相同的结果。它的通用性较低,但是可以解决OP的问题(那里只有父母和孩子,而没有“第三代”节点)。
就像其他答案一样,它的编写使得可以选择原始表中的所有列(或一些相关子集)。最好使用解析函数来完成,就像我在其他《答案》中所做的一样。
with
orders_table (order_id, parent_order_id) as (
select 1, null from dual union all
select 2, null from dual union all
select 3, null from dual union all
select 4, null from dual union all
select 5, 1 from dual union all
select 6, 2 from dual union all
select 7, 3 from dual union all
select 8, 3 from dual
)
select order_id, parent_order_id
from (
select o.*
, max(order_id) over
(partition by coalesce(parent_order_id, order_id)) as max_id
from orders_table o
)
where order_id = max_id
;