将递归CTE从后SQL转换为SQL Server
我很难适应一些递归CTE代码从PostgreSQL到SQL Server。
这是我的桌子:
CREATE TABLE flight (
src CHAR(3)
, dest CHAR(3)
, stt DATETIME
, endt DATETIME);
INSERT INTO flight VALUES
('MSP', 'SLC', '2022-10-02 11:45:00', '2022-10-02 14:10:00'),
('SLC', 'LAX', '2022-10-02 15:20:00', '2022-10-02 17:45:00'),
('MSP', 'LAX', '2022-10-02 12:15:00', '2022-10-02 15:05:00')
我要适应的东西:
WITH RECURSIVE flight_paths (src, flights, path, dest, stt, endt) AS (
SELECT
src
, ARRAY[src || '-' || dest]
, ARRAY[src]
, dest
, stt
, endt
FROM flight
UNION ALL
SELECT
fp.src
, fp.flights || (f.src || '-' || f.dest)
, fp.path || f.src
, f.dest
, fp.stt
, f.endt
FROM flight f
JOIN flight_paths fp ON f.src = fp.dest
WHERE NOT f.src = ANY(fp.path)
AND NOT 'LAX' = ANY(fp.path)
AND f.stt > fp.endt
)
SELECT flights, stt, endt, path[2:] stopovers
FROM flight_paths
WHERE src = 'MSP' AND dest = 'LAX'
我一直在适应阵列使用的问题。任何指针都会有所帮助!
I am having trouble adapting some recursive CTE code from PostgreSQL to SQL Server.
Here is my table:
CREATE TABLE flight (
src CHAR(3)
, dest CHAR(3)
, stt DATETIME
, endt DATETIME);
INSERT INTO flight VALUES
('MSP', 'SLC', '2022-10-02 11:45:00', '2022-10-02 14:10:00'),
('SLC', 'LAX', '2022-10-02 15:20:00', '2022-10-02 17:45:00'),
('MSP', 'LAX', '2022-10-02 12:15:00', '2022-10-02 15:05:00')
and what I am trying to adapt:
WITH RECURSIVE flight_paths (src, flights, path, dest, stt, endt) AS (
SELECT
src
, ARRAY[src || '-' || dest]
, ARRAY[src]
, dest
, stt
, endt
FROM flight
UNION ALL
SELECT
fp.src
, fp.flights || (f.src || '-' || f.dest)
, fp.path || f.src
, f.dest
, fp.stt
, f.endt
FROM flight f
JOIN flight_paths fp ON f.src = fp.dest
WHERE NOT f.src = ANY(fp.path)
AND NOT 'LAX' = ANY(fp.path)
AND f.stt > fp.endt
)
SELECT flights, stt, endt, path[2:] stopovers
FROM flight_paths
WHERE src = 'MSP' AND dest = 'LAX'
I have been having issues adapting the use of ARRAYs. Any pointers would be really helpful!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
更快的更快是:
用100003行测试,结果是:
在Windows 2019 evelptper / PC上运行256 GO RAM和24个核心X 2 Intel Xeon CPU E5-1650 V4
结论:JSON或XML的递归查询非常昂贵...
Much more quicker will be :
Tested with 100003 rows, the results are :
Running on a Windows 2019 Developper / PC with 256 Go RAM and 24 cores x 2 intel Xeon CPU E5-1650 v4
Conclusion : JSON or XML are very costly in recursive queries...
不幸的是,SQL Server不支持数组。但是您可以使用JSON数组。
您的原始代码的一个非常直接的副本会导致
逻辑上的一些微小变化:
路径
仅构建中间节点,并进行单独的检查以排除起点。我注意到,明确检查目的地是否尚未达到目的地,并且将起始点推入CTE的锚点:
db<>> fiddle
, f.src) , f.dest , fp.stt , f.endt FROM flight f JOIN flight_paths fp ON f.src = fp.dest AND f.dest <> fp.src AND fp.dest <> 'LAX' WHERE EXISTS (SELECT 1 FROM OPENJSON(fp.path) arr WHERE arr.value <> f.src ) AND f.stt > fp.endt ) SELECT flights, stt, endt, path stopovers FROM flight_paths WHERE dest = 'LAX';db&lt;&gt;&gt; fiddle
, f.src + '-' + f.dest) , JSON_MODIFY(fp.path, 'append逻辑上的一些微小变化:
路径
仅构建中间节点,并进行单独的检查以排除起点。我注意到,明确检查目的地是否尚未达到目的地,并且将起始点推入CTE的锚点:
db&lt;&gt;&gt; fiddle
, f.src) , f.dest , fp.stt , f.endt FROM flight f JOIN flight_paths fp ON f.src = fp.dest AND f.dest <> fp.src WHERE EXISTS (SELECT 1 FROM OPENJSON(fp.path) arr WHERE arr.value NOT IN(f.src, 'LAX') ) AND f.stt > fp.endt ) SELECT flights, stt, endt, path stopovers FROM flight_paths WHERE src = 'MSP' AND dest = 'LAX'逻辑上的一些微小变化:
路径
仅构建中间节点,并进行单独的检查以排除起点。我注意到,明确检查目的地是否尚未达到目的地,并且将起始点推入CTE的锚点:
db&lt;&gt;&gt; fiddle
Unfortunately, SQL Server does not support arrays. But you could use a JSON array instead.
A pretty straight-up copy of your original code results in this
Some minor changes in the logic were necessary:
path
only builds the intermediate nodes, and a separate check is made to exclude the start point.I note that it's probably faster to check explicitly that the destination has not been reached, and also to push the start point into the anchor part of the CTE:
db<>fiddle
, f.src) , f.dest , fp.stt , f.endt FROM flight f JOIN flight_paths fp ON f.src = fp.dest AND f.dest <> fp.src AND fp.dest <> 'LAX' WHERE EXISTS (SELECT 1 FROM OPENJSON(fp.path) arr WHERE arr.value <> f.src ) AND f.stt > fp.endt ) SELECT flights, stt, endt, path stopovers FROM flight_paths WHERE dest = 'LAX';db<>fiddle
, f.src + '-' + f.dest) , JSON_MODIFY(fp.path, 'appendSome minor changes in the logic were necessary:
path
only builds the intermediate nodes, and a separate check is made to exclude the start point.I note that it's probably faster to check explicitly that the destination has not been reached, and also to push the start point into the anchor part of the CTE:
db<>fiddle
, f.src) , f.dest , fp.stt , f.endt FROM flight f JOIN flight_paths fp ON f.src = fp.dest AND f.dest <> fp.src WHERE EXISTS (SELECT 1 FROM OPENJSON(fp.path) arr WHERE arr.value NOT IN(f.src, 'LAX') ) AND f.stt > fp.endt ) SELECT flights, stt, endt, path stopovers FROM flight_paths WHERE src = 'MSP' AND dest = 'LAX'Some minor changes in the logic were necessary:
path
only builds the intermediate nodes, and a separate check is made to exclude the start point.I note that it's probably faster to check explicitly that the destination has not been reached, and also to push the start point into the anchor part of the CTE:
db<>fiddle