递归 sql 查询中的无限循环
Infinity loop in recursive sql query
也许有人会建议我如何解决我的问题。
我不知道为什么会发生以及如何解决它。
在我看来,我的 sql 代码不起作用的原因
是它变成了不定式循环。
我有 table:
CREATE TABLE `c_logistics_tran_group3` (
`ltrgr_id` int(10) UNSIGNED NOT NULL,
`ltrgr_lagr_id` int(10) UNSIGNED NOT NULL,
`ltrgr_ltran_id` int(10) UNSIGNED NOT NULL,
`ltrgr_created` timestamp NOT NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `c_logistics_tran_group3`
ADD PRIMARY KEY (`ltrgr_id`),
ADD UNIQUE KEY `ltrgr_lagr_id` (`ltrgr_lagr_id`,`ltrgr_ltran_id`),
ADD KEY `c_logistics_tran_group3_ibfk_2` (`ltrgr_ltran_id`);
ALTER TABLE `c_logistics_tran_group3`
MODIFY `ltrgr_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
和数据:
INSERT INTO `c_logistics_tran_group3`
(`ltrgr_id`, `ltrgr_lagr_id`, `ltrgr_ltran_id`, `ltrgr_created`)
VALUES
(2373, 2154, 2312, '2021-09-09 07:54:55'),
(2378, 2154, 2314, '2021-09-09 08:05:25'),
(2382, 2154, 2318, '2021-09-09 10:37:37'),
(2450, 2154, 2386, '2021-09-17 11:44:58'),
(2375, 2156, 2312, '2021-09-09 07:57:14'),
(2380, 2156, 2316, '2021-09-09 10:25:01'),
(2381, 2156, 2317, '2021-09-09 10:37:07'),
(2451, 2156, 2387, '2021-09-17 11:45:37'),
(2376, 2157, 2312, '2021-09-09 08:03:10'),
(2387, 2157, 2323, '2021-09-10 10:36:15'),
(2388, 2157, 2324, '2021-09-10 10:42:59'),
(2449, 2157, 2385, '2021-09-17 11:41:36'),
(2377, 2158, 2312, '2021-09-09 08:04:35');
COMMIT;
我的sql代码:
with
recursive
edges as (
select t1.ltrgr_lagr_id as lagr_id1, t2.ltrgr_lagr_id as lagr_id2
from c_logistics_tran_group3 t1
inner join c_logistics_tran_group3 t2 on t2.ltrgr_ltran_id = t1.ltrgr_ltran_id
where 1 = 1
and t1.ltrgr_lagr_id in(2154, 2156, 2157, 2158)
and t2.ltrgr_lagr_id in(2154, 2156, 2157, 2158)
),
cte as (
select lagr_id1, lagr_id2, concat(lagr_id1, ',', lagr_id2) as visited
from edges
union all
select c.lagr_id1, e.lagr_id2, concat(c.visited, ',', e.lagr_id2)
from cte c
inner join edges e on e.lagr_id1 = c.lagr_id2
where not find_in_set(e.lagr_id2, c.visited)
)
select * from cte;
此 SQL 代码执行此处描述的任务:
如果我从列表中删除任何 lagr_id 一切正常。例如:
and t1.ltrgr_lagr_id in(2154, 2156, 2157)
and t2.ltrgr_lagr_id in(2154, 2156, 2157)
当列表中有 4 个 lagr_id 时,我的 sql 代码挂断了。只有服务器重启有帮助:(
有人对如何解决这个问题有任何想法吗?如何避免我的 sql 代码中的无限循环?
MariaDB 版本 10.5.12
这不是无限循环,但您 运行 资源不足。
您可以通过这种方式改进您的查询:
- 我在
edges
子查询中添加 DISTINCT
子句以避免重复行。
- 我在
cte
子查询中添加 CASE
语句以避免在 visited
列中设置两次相同的值(当 lagr_id1 = lagr_id2 时)。
- 我将
UNION ALL
替换为 UNION
以避免重复的行。
WITH
RECURSIVE
edges AS (
SELECT DISTINCT t1.ltrgr_lagr_id AS lagr_id1, t2.ltrgr_lagr_id AS lagr_id2
FROM c_logistics_tran_group3 t1
INNER JOIN c_logistics_tran_group3 t2 ON t2.ltrgr_ltran_id = t1.ltrgr_ltran_id
WHERE t1.ltrgr_lagr_id in(2154, 2156, 2157, 2158)
AND t2.ltrgr_lagr_id in(2154, 2156, 2157, 2158)
),
cte AS (
SELECT lagr_id1, lagr_id2, CASE WHEN lagr_id1 = lagr_id2 THEN lagr_id1 ELSE concat(lagr_id1, ',', lagr_id2) END AS visited
FROM edges
UNION
SELECT c.lagr_id1, e.lagr_id2, concat(c.visited, ',', e.lagr_id2)
FROM cte c
INNER JOIN edges e ON e.lagr_id1 = c.lagr_id2
WHERE NOT find_in_set(e.lagr_id2, c.visited)
)
SELECT * FROM cte;
行数大大减少,但我认为我的查询可以改进,例如visited
值'2154,2156,2158,2157'是与'2154,2156,2157,2158'相同,因为组合的顺序在结果中并不重要,所以查询应该丢弃其中一个。
也许有人会建议我如何解决我的问题。 我不知道为什么会发生以及如何解决它。 在我看来,我的 sql 代码不起作用的原因 是它变成了不定式循环。 我有 table:
CREATE TABLE `c_logistics_tran_group3` (
`ltrgr_id` int(10) UNSIGNED NOT NULL,
`ltrgr_lagr_id` int(10) UNSIGNED NOT NULL,
`ltrgr_ltran_id` int(10) UNSIGNED NOT NULL,
`ltrgr_created` timestamp NOT NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `c_logistics_tran_group3`
ADD PRIMARY KEY (`ltrgr_id`),
ADD UNIQUE KEY `ltrgr_lagr_id` (`ltrgr_lagr_id`,`ltrgr_ltran_id`),
ADD KEY `c_logistics_tran_group3_ibfk_2` (`ltrgr_ltran_id`);
ALTER TABLE `c_logistics_tran_group3`
MODIFY `ltrgr_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
和数据:
INSERT INTO `c_logistics_tran_group3`
(`ltrgr_id`, `ltrgr_lagr_id`, `ltrgr_ltran_id`, `ltrgr_created`)
VALUES
(2373, 2154, 2312, '2021-09-09 07:54:55'),
(2378, 2154, 2314, '2021-09-09 08:05:25'),
(2382, 2154, 2318, '2021-09-09 10:37:37'),
(2450, 2154, 2386, '2021-09-17 11:44:58'),
(2375, 2156, 2312, '2021-09-09 07:57:14'),
(2380, 2156, 2316, '2021-09-09 10:25:01'),
(2381, 2156, 2317, '2021-09-09 10:37:07'),
(2451, 2156, 2387, '2021-09-17 11:45:37'),
(2376, 2157, 2312, '2021-09-09 08:03:10'),
(2387, 2157, 2323, '2021-09-10 10:36:15'),
(2388, 2157, 2324, '2021-09-10 10:42:59'),
(2449, 2157, 2385, '2021-09-17 11:41:36'),
(2377, 2158, 2312, '2021-09-09 08:04:35');
COMMIT;
我的sql代码:
with
recursive
edges as (
select t1.ltrgr_lagr_id as lagr_id1, t2.ltrgr_lagr_id as lagr_id2
from c_logistics_tran_group3 t1
inner join c_logistics_tran_group3 t2 on t2.ltrgr_ltran_id = t1.ltrgr_ltran_id
where 1 = 1
and t1.ltrgr_lagr_id in(2154, 2156, 2157, 2158)
and t2.ltrgr_lagr_id in(2154, 2156, 2157, 2158)
),
cte as (
select lagr_id1, lagr_id2, concat(lagr_id1, ',', lagr_id2) as visited
from edges
union all
select c.lagr_id1, e.lagr_id2, concat(c.visited, ',', e.lagr_id2)
from cte c
inner join edges e on e.lagr_id1 = c.lagr_id2
where not find_in_set(e.lagr_id2, c.visited)
)
select * from cte;
此 SQL 代码执行此处描述的任务:
如果我从列表中删除任何 lagr_id 一切正常。例如:
and t1.ltrgr_lagr_id in(2154, 2156, 2157)
and t2.ltrgr_lagr_id in(2154, 2156, 2157)
当列表中有 4 个 lagr_id 时,我的 sql 代码挂断了。只有服务器重启有帮助:( 有人对如何解决这个问题有任何想法吗?如何避免我的 sql 代码中的无限循环? MariaDB 版本 10.5.12
这不是无限循环,但您 运行 资源不足。
您可以通过这种方式改进您的查询:
- 我在
edges
子查询中添加DISTINCT
子句以避免重复行。 - 我在
cte
子查询中添加CASE
语句以避免在visited
列中设置两次相同的值(当 lagr_id1 = lagr_id2 时)。 - 我将
UNION ALL
替换为UNION
以避免重复的行。
WITH
RECURSIVE
edges AS (
SELECT DISTINCT t1.ltrgr_lagr_id AS lagr_id1, t2.ltrgr_lagr_id AS lagr_id2
FROM c_logistics_tran_group3 t1
INNER JOIN c_logistics_tran_group3 t2 ON t2.ltrgr_ltran_id = t1.ltrgr_ltran_id
WHERE t1.ltrgr_lagr_id in(2154, 2156, 2157, 2158)
AND t2.ltrgr_lagr_id in(2154, 2156, 2157, 2158)
),
cte AS (
SELECT lagr_id1, lagr_id2, CASE WHEN lagr_id1 = lagr_id2 THEN lagr_id1 ELSE concat(lagr_id1, ',', lagr_id2) END AS visited
FROM edges
UNION
SELECT c.lagr_id1, e.lagr_id2, concat(c.visited, ',', e.lagr_id2)
FROM cte c
INNER JOIN edges e ON e.lagr_id1 = c.lagr_id2
WHERE NOT find_in_set(e.lagr_id2, c.visited)
)
SELECT * FROM cte;
行数大大减少,但我认为我的查询可以改进,例如visited
值'2154,2156,2158,2157'是与'2154,2156,2157,2158'相同,因为组合的顺序在结果中并不重要,所以查询应该丢弃其中一个。