簡體   English   中英

獲取所有沒有孩子的父母,或者如果有孩子,請獲取最新的孩子

[英]get All Parents with no children or if there are children, get the latest child

我有下表的命令。 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。

謝謝您的幫助。

這是解決此問題的一種方法,即使用connect by查詢connect by (實際上是一種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查詢進行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
;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM