我需要Sybase IQ并且需要在表格上构建一个树,包含超过一百万条记录,每个order_id
链接一次。我需要找到它被现有order_id
替换的内容直到结束。最后,我还需要找到每个order_id
的各种数量,并从中获得最大数量。
版本信息:
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');
预期输出
答案 0 :(得分:0)
这是我迄今为止所做的以及它在自我加入方面的作用。 我唯一担心的是自我加入是缓慢或相当混乱。
我也尝试用锚点(但在Oracle中)进行CTE同样的要求。不幸的是,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;
最后一步,为了拥有一个干净的表集,我从#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;
我正在努力寻找更好的解决方案。
有什么建议吗?