【问题标题】:Recursive CTE to find all records SQL Server递归 CTE 查找所有记录 SQL Server
【发布时间】:2017-12-04 09:25:50
【问题描述】:

我有下表结构。我想编写一个递归 cte 来获得最底部的表格结果。 非常感谢您的帮助。

CREATE TABLE Jobcard (
  jobcard_id INT NOT NULL PRIMARY KEY,
  jobcard_name varchar(20) NOT NULL,
);
CREATE TABLE Vehicle (
  vehicle_id INT NOT NULL PRIMARY KEY,
  vehicle_name varchar(20) NOT NULL
);

CREATE TABLE Jobacard_vehicle (
  jobcard_id INT NOT NULL,
  vehicle_id INT NOT NULL
);


INSERT INTO Jobcard (jobcard_id, jobcard_name) VALUES
(1, 'Job1'),(2, 'Job2'),(3, 'Job3'),
(4, 'Job4'),(5, 'Job5'),(6, 'Job6'),
(7, 'Job7'),(8, 'Job8'),(9, 'Job9');

INSERT INTO Vehicle (vehicle_id, vehicle_name) VALUES
(1, 'Vehicle1'),(2, 'Vehicle2'),(3, 'Vehicle3'),
(4, 'Vehicle4'),(5, 'Vehicle5'),(6, 'Vehicle6');

INSERT INTO Jobacard_vehicle (jobcard_id, vehicle_id) VALUES
(3, 1),(4, 2),(5, 3),
(9, 6),(7, 2),(5, 4),
(8, 4),(6, 1),(3, 5);
jobcard_id, vehicle_id
--------------------------
3           1
4           2
5           3
9           6
7           2
5           4
8           4
6           1
3           5

I want to get this result from Jobacard_vehicle table when I pass the vehicle id as 3 as 

车辆 ID 3 拥有工作卡 5 工作卡 5 有车辆 4 再次将车辆 4 称为工作卡 8 是指所有由3或其对应的jobcards车辆引用的jobcard

jobcard_id, vehicle_id
--------------------------
5           3
5           4
8           4

谢谢。

【问题讨论】:

  • 嗨..首先我要感谢你用脚本解释这个问题。
  • 您是否已经编写了任何脚本来实现此目标?我的意思是你开发的脚本有什么问题吗?
  • 嗨朋友,是的,我正在尝试使用这个脚本,;with temp as( SELECT jobcard_id, vehicle_id FROM Jobacard_vehicle b2m WHERE vehicle_id = 3 UNION ALL SELECT bi.jobcard_id ,bi.vehicle_id FROM Jobacard_vehicle bi JOIN temp x ON bi.jobcard_id = x.jobcard_id AND x.vehicle_id bi.vehicle_id ) select * from temp option (maxrecursion 0)

标签: sql sql-server common-table-expression recursive-query


【解决方案1】:

尝试保存完整路径并在下一次递归中检查它

DECLARE @startVehicleID int=3

;WITH vehCTE AS(
    SELECT jobcard_id,vehicle_id,CAST(CONCAT('(',jobcard_id,',',vehicle_id,')') AS varchar(MAX)) [path]
    FROM Jobacard_vehicle
    WHERE vehicle_id=@startVehicleID

    UNION ALL

    SELECT v.jobcard_id,v.vehicle_id,c.[path]+CONCAT('(',v.jobcard_id,',',v.vehicle_id,')')
    FROM Jobacard_vehicle v
    JOIN vehCTE c ON (v.jobcard_id=c.jobcard_id OR v.vehicle_id=c.vehicle_id) AND CHARINDEX(CONCAT('(',v.jobcard_id,',',v.vehicle_id,')'),c.[path])=0
)
SELECT *
FROM vehCTE
ORDER BY [path]

如果你需要检查Job->Vehicle->Job->Vehicle->...那么我认为你可以使用以下

DECLARE @startVehicleID int=3

;WITH vehCTE AS(
    SELECT
        jobcard_id,
        vehicle_id,
        CAST(CONCAT('(',jobcard_id,',',vehicle_id,')') AS varchar(MAX)) [path],
        1 NextIsJob
    FROM Jobacard_vehicle
    WHERE vehicle_id=@startVehicleID

    UNION ALL

    SELECT
        v.jobcard_id,
        v.vehicle_id,
        c.[path]+CONCAT('(',v.jobcard_id,',',v.vehicle_id,')'),
        IIF(c.NextIsJob=1,0,1)
    FROM Jobacard_vehicle v
    JOIN vehCTE c ON ((c.NextIsJob=1 AND v.jobcard_id=c.jobcard_id) OR (c.NextIsJob=0 AND v.vehicle_id=c.vehicle_id)) AND CHARINDEX(CONCAT('(',v.jobcard_id,',',v.vehicle_id,')'),c.[path])=0
)
SELECT *
FROM vehCTE
ORDER BY [path]

【讨论】:

  • 不客气!并查看@startVehicleID int=1 的案例。在这种情况下,您有两个起点和两条不同的路径。对你来说正常吗?
猜你喜欢
  • 2011-04-25
  • 2018-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-23
  • 2014-05-19
  • 1970-01-01
相关资源
最近更新 更多