2017-01-10 10 views
0

Мне нужен Sybase IQ и нужно построить дерево на столе, которое содержит более миллиона записей, которые ссылаются на каждые order_id. Мне нужно найти то, что было заменено существующим order_id до конца. В конце концов, мне также нужно найти различные количества каждого из этих order_id и получить максимум от него.Sybase IQ SQL Рекурсивный цикл для построения дерева

Version Info:

select @@version 
SAP IQ/16.0.110.2014/10214/P/sp11/Enterprise Linux64 - x86_64 - 2.6.18-194.el5/64bit/2015-11-21 01:29:07 

Таблица DDL

create table #tmporder 
(
account_key varchar(50) not null, 
order_id varchar(50) not null, 
msg_type varchar(5) not null, 
repl_by_order varchar(50) not null, 
replaces_order varchar(50) not null, 
quantity numeric(12) not null, 
order_datetime datetime not null, 
order_status varchar(1) not null 
); 

Образец данных:

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6473','PL','0','0',1000,{ts '2016-10-07 07:59:10'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6473','MO','6480','0',1000,{ts '2016-10-07 07:59:10'},'5'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6474','PL','0','0',1000,{ts '2016-10-07 08:16:05'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6474','MO','6477','0',1000,{ts '2016-10-07 08:16:05'},'5'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6475','PL','0','0',1000,{ts '2016-10-07 08:16:18'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6475','MO','6476','0',1000,{ts '2016-10-07 08:16:18'},'5'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6476','MO','0','6475',1000,{ts '2016-10-07 08:18:59'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6477','MO','0','6474',1000,{ts '2016-10-07 08:19:39'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6477','MO','6478','6474',1000,{ts '2016-10-07 08:19:39'},'5'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6478','MO','6479','6477',1000,{ts '2016-10-07 08:25:42'},'5'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6478','MO','0','6477',1000,{ts '2016-10-07 08:25:42'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6479','MO','0','6478',1000,{ts '2016-10-07 08:29:00'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6480','MO','6481','6473',2000,{ts '2016-10-07 08:33:57'},'5'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6480','MO','0','6473',2000,{ts '2016-10-07 08:33:57'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6481','MO','0','6480',2000,{ts '2016-10-07 08:35:40'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6481','MO','6482','6480',2000,{ts '2016-10-07 08:35:40'},'5'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6482','MO','0','6481',2000,{ts '2016-10-07 08:36:40'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6484','PL','0','0',4000,{ts '2016-10-07 08:45:42'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6485','PL','0','0',1000,{ts '2016-10-07 08:46:30'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6486','PL','0','0',1000,{ts '2016-10-07 09:10:19'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6495','PL','0','0',1000,{ts '2016-10-07 17:54:10'},'1'); 

INSERT INTO #tmporder (account_key,order_id,msg_type,repl_by_order,replaces_order,quantity,order_datetime,order_status) 
VALUES ('123456','6496','PL','0','0','500',{ts '2016-10-07 18:05:24.0'},'1'); 

Ожидаемый результат:

  • Заказать ID: 6473, относящиеся Заказы ID: 6473/6480/6481/6482, Макс (кол-во): 2000
  • Заказать ID: 6474, родственного Приказы ID: 6474/6477/6478/6479, Макс. (Кол-во): 1000
  • Идентификационный номер заказа: 6475, Соответствующие заказы ID: 6475/6476, Макс. Кол-во: 1000
  • Идентификационный номер заказа: 6484, Соответствующие заказы ID:, Макс Кол-во: 4000
  • Идентификационный номер заказа: 6485, Соответствующие заказы ID:, Макс. Кол-во: 1000

ответ

0

Вот то, что я сделал до сих пор, и Его на себя объединяет. Моя единственная забота о самостоятельном соединении - медленная или довольно грязная.

Я также пробовал делать CTE с якорем (но в Oracle) для того же требования. К сожалению, Sybase IQ не поддерживает RECURSIVE. (Это дает мне всевозможные ошибки, например: RECURSIVE не разрешен, «Удаленный сервер не может поддерживать это заявление»

Так что на данный момент я внедрил грубую . способ (для понимания, я разделить на несколько шагов)

Населенные первоначально с корневыми элементами, путем создания временной таблицы иерархии:

create table #tmporder_hier 
(
account_key varchar(50) not null, 
order_id varchar(50) not null, 
replaces_order varchar(50) not null, 
quantity numeric(12) not null, 
root  varchar(20)  not null, 
path  varchar(600) not null, 
depth int    not null, 
multiple_qty  varchar(600) not null, 
max_quantity numeric(12) null 
); 

insert into #tmporder_hier (account_key,order_id,replaces_order,quantity,root,path,depth,multiple_qty,max_quantity) 
select e.account_key,e.order_id,e.replaces_order,e.quantity, 
     e.order_id as root, 
     '/' + e.order_id as path, 
     1 as depth, 
     '/' + convert(varchar(20),e.quantity) as multiple_qty, 
     null as max_quantity 
from 
#tmporder e 
where e.repl_by_order = '0' AND e.replaces_order = '0'; 

Затем я применяю петлю, чтобы выяснить, дочерние записи для каждого из родителя и заполнить PATH.

DECLARE @i int 
DECLARE @rowcount int 
set @i=1; 
while @i <= 15 
BEGIN 
     insert into #tmporder_hier(account_key,order_id,replaces_order,quantity,root,path,depth,multiple_qty,max_quantity) 
     with tmpcte as 
     (select * from #tmporder_hier) 
     SELECT distinct e.account_key,e.order_id,e.replaces_order,e.quantity 
     ,e.replaces_order as root, 
     t.path + '/' + e.order_id as path, 
     @i + 1 as depth, 
     t.multiple_qty + '/' + convert(varchar(20),e.quantity) as multiple_qty,null as max_quantity 
     FROM #tmporder e , tmpcte t 
     WHERE exists (
          SELECT 1 
           FROM #tmporder_hier h1 
           where e.replaces_order = h1.order_id 
           and e.account_key = h1.account_key 
          ) 
     and e.replaces_order = t.order_id 
     and not exists (select 1 from tmpcte t1 where e.order_id = t1.order_id and e.account_key = t1.account_key) 
     set @rowcount = @@ROWCOUNT 
     if (@rowcount = 0) 
     break 
     set @i = @i + 1 
END 

Затем, как третий шаг, я обновляю ROOT с соответствующими вводами.

update #tmporder_hier 
set root = case when charindex('/',right(path,char_length(path)-1))-1 = -1 
      then substring(path,2,char_length(path)-1) 
     else 
      substring(path,2,charindex('/',right(path,char_length(path)-1))-1) 
     end, 
    path = case when depth = 1 
      then '''' + substring(path,2,char_length(path)-1) + '''' 
     else 
      ''''+str_replace(substring(path,2,char_length(path)-1),'/',''',''') + '''' 
     end; 

и последний шаг, Просто, чтобы иметь чистую TableSet, я удалить ненужные записи из #tmporder_hier:

select *,max(depth) over (partition by account_key,root) as max_depth into #tmporder_hier_new 
           from #tmporder_hier; 


delete from #tmporder_hier_new 
where 0 = case when depth = max_depth then 1 else 0 end; 

Я пытаюсь найти лучшее решение.

Любое предложение?

 Смежные вопросы

  • Нет связанных вопросов^_^