我必须提出另一个问题,这已经使我花费了几个小时,而我却无法解决它。我需要在PostgreSQL中编写一个递归查询(用于univercity)。我有一个称为“ basedOn”的关系,其中计算机基于其他(旧)版本,例如:
CREATE TABLE BasedON(
fromID integer,
fromSize numeric,
toID integer,
toSize numeric,
...
);
我需要知道使用递归查询查找基于其他版本的所有可传递版本(例如,如果A基于B,而B基于C,A基于C)。我现在的问题是,我还必须针对“基于B的B,基于C的B和基于A的C”的循环解决此问题,在该循环中我的查询会无限循环。那就是我的查询现在的样子:
WITH RECURSIVE tmp(fromID, fromSize, toID, toSize,c) AS (
SELECT fromID, fromSize, toID, toSize, 0 FROM BasedOn
WHERE toID= 0 AND toSize= 2.0 --start
UNION
SELECT b.fromID, b.fromSize, t.toID,t.toSIze, c+1 AS steps
FROM BasedOn b JOIN tmp t ON
t.fromID= b.toID AND t.fromSize= b.toSize
)SELECT * FROM tmp;
“ c”仅用于“计算”递归步骤。它适用于非循环数据。但是,如果我在数据中插入一个循环,则会无限循环。有没有人给小费,如何避免这种情况? 提前致谢, 卢卡斯
SampleData:
INSERT INTO BasedOn VALUES
(7000, 1.28, 7003, 2.52),
(7003, 2.52, 7006, 0.98), --cycle
(7006, 0.98, 7009, 4.18),
(7006, 0.98, 7003, 2.52), --cycle
(7009, 4.18, 7015, 1.33),
(7009, 4.18, 0, 2.00);
预期输出:
fromID, fromSize, toID, toSize,stepcount
7009 4.18 0 2.00 0
7006 0.98 0 2.00 1
7003 2.52 0 2.00 2
7000 1.28 0 2.00 3
答案 0 :(得分:1)
去那里:
const App:React.FC<Props>=(props:Props)=> {
const [data, setData] = React.useState<MyInterface[]>(props.values);
const handleChange = (e: ChangeEvent<HTMLInputElement>,id:number) => {
const amount = parseInt(e.target.value, 10);
const temp:MyInterface[] = data.map(d => d.id === id? {...d,amount} : d)
setData(temp);
};
const upload = ()=> { /* POST the state array to server */}
return (
<>
{data.map(d=> (
<div>
<input value={d.amount} onChange={handleChange} />
<button onClick={upload}/>
</div>
))}
</>
);
}
结果:
\i tmp.sql
CREATE TABLE based_on(
from_id integer
, from_size numeric
, to_id integer
, to_size numeric
);
INSERT INTO based_on VALUES
(7000, 1.28, 7003, 2.52),
(7003, 2.52, 7006, 0.98), --cycle
(7006, 0.98, 7009, 4.18),
(7006, 0.98, 7003, 2.52), --cycle
(7009, 4.18, 7015, 1.33),
(7009, 4.18, 0, 2.00);
-- I need know to find all transitive versions which base on others (like if A bases on B, and B on C, A bases on C) using a recursive Query. My Problem now is, that I have to solve this also for Cycles like "A bases on B, B on C, and C on A", where my query loops infinite. Thats what my query looks like now:
WITH RECURSIVE tmp(from_id, from_size, to_id, to_size,c,path) AS (
SELECT from_id, from_size, to_id, to_size
, 0
, array[from_id] AS path
FROM based_on
WHERE to_id= 0 AND to_size= 2.0 --start
UNION
SELECT b.from_id, b.from_size
, t.to_id,t.to_size
, c+1 AS steps
, t.path || b.from_id
FROM based_on b
JOIN tmp t ON t.from_id= b.to_id -- AND t.from_size= b.to_size
AND NOT b.from_id = ANY(t.path)
)
SELECT * FROM tmp;
答案 1 :(得分:1)
我只是为了好玩(?)而使用ARRAY
做练习。
无论如何,这是查询:
with recursive
s as (
select
*, tosize as converted_size, 0 as step_count,
array[-1]::int[] as walked, 1 as len from basedon
where toid = 0 and tosize = 2.0 -- starting node
union all
select b.*, s.converted_size, step_count + 1,
walked || b.fromid, array_length(walked, 1) + 1
from s
join basedon b on b.toid = s.fromid and b.tosize = s.fromsize
and not (b.fromid = any(walked))
)
select * from s;
结果:
fromid fromsize toid tosize converted_size step_count walked len
------ -------- ---- ------ -------------- ---------- ------------ ---
7009 4.18 0 2 2 0 <UnknownType 1
7006 0.98 7009 4.18 2 1 <UnknownType 2
7003 2.52 7006 0.98 2 2 <UnknownType 3
7000 1.28 7003 2.52 2 3 <UnknownType 4
这是我使用的数据脚本:
create table basedon (
fromid integer,
fromsize numeric,
toid integer,
tosize numeric
);
insert into basedon (fromid, fromsize, toid, tosize) values
(7000, 1.28, 7003, 2.52),
(7003, 2.52, 7006, 0.98), --cycle
(7006, 0.98, 7009, 4.18),
(7006, 0.98, 7003, 2.52), --cycle
(7009, 4.18, 7015, 1.33),
(7009, 4.18, 0, 2.00);