Sql 让所有没有孩子的父母,或者如果有孩子,让最新的孩子
我有下面的订单。orderId是主键,parentOrderId是表示此订单是否具有父订单的列 例:1,2,3,4没有父订单。5,6,7,8有上级订单Sql 让所有没有孩子的父母,或者如果有孩子,让最新的孩子,sql,Sql,我有下面的订单。orderId是主键,parentOrderId是表示此订单是否具有父订单的列 例:1,2,3,4没有父订单。5,6,7,8有上级订单 +--------------------+----------------------+ | order_id | parent_order_id | +--------------------+----------------------+ | 1 |
+--------------------+----------------------+
| 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.
我尝试的是:
我要找的是:
上面的查询返回4,5,6,8。问题是我将此查询输入IN子句,oracle对IN子句的限制为1000。我试图看看是否有更好的方法来解决这个问题使用连接。
更新:
联接将帮助我检索order表中的所有列,而不仅仅是id,为了简单起见,我只包括了两列,表中还有更多列。现在,我获取id的第一个,并在另一个查询中的子句中提供它们,以获取与这些id匹配的所有列
我也在寻找不是特定于供应商的sql
谢谢您的帮助。这里有一种解决此问题的方法,使用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
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
;
1000限值适用于a,即固定值列表;如果您直接使用子查询,即。。。在选择。。。联合所有。。。减从orders中,子查询可以返回的行数没有限制。也许有更好的方法可以做到这一点,但你可能是从一个错误的理解开始的。@alex poole感谢你的回答。按照应用程序的设计方式,我必须执行两个单独的查询,一个是获取所有有效id,另一个是使用in子句中的列表获取这些id的所有详细信息。我考虑的另一种选择是一次批处理1000个id,然后在第一组1000个id或第二组1000个id中进行……以此类推。不确定这样做是否正确。为什么5不能达到预期效果?它是我唯一的孩子。然后——分别地——如果父母有多个孩子,你如何定义最新的孩子?最新的,以什么标准衡量?简单地按照标签的字母顺序或数字顺序排列,所以8>7或字符串'8'>7'表示8是最新的?这很奇怪;如果有多个子项,是否有一个额外的列用于排序子项?另外:您的表是否只有父代和子代,或者链是否可以有三代或更多代?此外,您对1000多个结果的讨论以及使用联接等都没有意义。如果您执行现在正在执行的操作,保存结果,然后将它们硬编码到IN子句中,那么根据哪个查询生成1000多个结果,这种情况会发生什么变化?无论什么查询生成结果,无论它使用UNIONALL、join还是分层查询,都可能是最好的选择,您不会遇到完全相同的问题吗?解决方案是修改应用程序,以便在单个查询中完成所需的所有操作。否则,必须创建一个临时表,将第一个查询的结果保存到该表中,然后从临时表中选择in条件。但与正确答案相比,这是一个相当蹩脚的解决方案,正确答案是在一个查询中获取所有内容。谢谢@mathguy。看起来没有连接方式的解决方案是不可能的?我问的原因是我需要将上述查询转换为查询dsl jpa查询,我可能无法这样做,因为这是特定于oracle的。完全可以使用join语法重写此查询。当我有时间的时候,我会提出一种方法。然而,这些限制应该永远是你问题的一部分;现在,在你的原始帖子中没有关于它的任何内容,标签只是sql和oracle-没有迹象表明oracle解决方案不适合你。同意,我的错。但我会记住这一点。我的印象是,我应该能够翻译任何sql查询,但忽略了一个事实,即在本例中,查询可以是特定于供应商的Oracle。非常感谢您的回复,谢谢。这个使用group by的修改版本同样有效:select*from orders\U table,其中order\U id位于select maxorder\U id中
通过合并父级订单id、订单id从订单表组@rohith-好的,但是在查询中,您从表中读取了两次数据。引入分析函数的具体目的是避免这种需要——多次读取数据。
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
;