我认为您必须分两步执行此操作 - 首先对排序顺序进行排序,然后进行实际查询。我怀疑获得排序顺序可能会很昂贵(我想不出一种不循环或递归的方法),所以如果可能的话,你应该避免比你必须更频繁地这样做。如果您的 table2 不经常更改,并且您可以更改设计,我会很想将该表中的实际排序顺序存储在一个额外的列中。
任何时候 table2 被修改,您必须在再次运行此查询之前更新排序顺序。因为要更新排序顺序可能需要多次 table2 编辑,并且顺序实际上会被破坏,直到最后一个,我可能会在表上放置一个触发器来设置一个顺序需要更新的标志。您可以在运行此查询之前检查标志,或在夜间维护运行(以先到者为准)并根据需要更新订单。
如果您无法更改数据库,您可以在每次查询运行之前进行排序,但根据您的数据,它可能会减慢很多速度。
无论如何,要弄清楚排序顺序,您需要为 table2 中的每一行创建一个 orderno(直接更新行,或在单独的临时表中。看起来您在数据中有许多订单列表, 每个 headerID 一个。您可以通过首先找到每个链的开始行来创建订单(我假设 begin_ID 为空),然后给他们 orderNo 1。然后在循环中,找到应该是下一个 orderno 的行, 并将其分配给他们,直到你找不到更多。如果最后有任何行没有分配 orderNo,那么你有数据问题。
--Set up the work table
DECLARE @Work TABLE (Sub_ID int, orderNo int);
-- Set up the start of each order list
insert into @Work (sub_ID, orderNo)
Select sub_ID, 1
from table2
where begin_ID is null;
DECLARE @Finished int = 0; --Flag to see if we're done
DECLARE @NextOrder int = 2; --Next order number to process
While @Finished = 0
BEGIN
-- add the next level for all the order lists
insert into @Work (sub_ID, orderNo)
Select t2.sub_ID, @NextOrder
From table2 t2
inner join @Work w on w.sub_ID = t2.begin_ID -- We want rows that are next in an order chain
left outer join @Work w2 on w2.sub_ID = t2.sub_ID -- and haven't already been done (to avoid loops)
Where w2.Sub_ID is null;
IF @@ROWCOUNT = 0 SET @Finished = 1; --flag if nothing was updated (so stop)
SET @NextOrder = @NextOrder + 1; -- next order level to add
END;
--example usage of order table. Note that any records where w.sub_id is null means
-- that record was not in a reachable order list (either the table2 record does not
-- exist, or the order list walk never reached it).
Select t1.*
from table1 t1
left outer join @Work w on w.sub_ID = t1.sub_id
order by T1.head_id, w.orderNo
您也可以使用递归 CTE 来做到这一点,但原理是一样的。如果 IMPALA 需要以这种方式工作,这将让您在一个查询中完成所有操作。