Ecco il mio scenario. Diciamo che ho due tavoli "Car" e "CarPart". L'auto è composta da molte parti e ogni parte può appartenere a più auto. Una delle complicazioni nel mio caso è che ogni parte riceve un nuovo PartID, anche se è lo stesso nome di parte, ma appartiene semplicemente a un'auto diversa. Questo è qualcosa su cui non ho controllo, quindi portami con me. Ecco la sceneggiatura per impostare le cose.Quota T-SQL ricorsiva impegnativa
IF OBJECT_ID('Car') IS NOT NULL DROP TABLE Car
CREATE TABLE Car (
CarID INT,
CarName VARCHAR(16)
)
IF OBJECT_ID('CarPart') IS NOT NULL DROP TABLE CarPart
CREATE TABLE CarPart (
PartID INT,
PartName VARCHAR(16),
CarID INT
)
INSERT INTO Car
VALUES (1, 'Chevy'),
(2, 'Ford'),
(3, 'Toyota'),
(4, 'Honda'),
(5, 'Nissan'),
(6, 'Hugo')
INSERT INTO CarPart
VALUES (110, 'Engine', 1),
(120, 'Engine', 2),
(210, 'Door', 1),
(220, 'Door', 3),
(310, 'Seat', 4),
(320, 'Seat', 5),
(410, 'Window', 3),
(510, 'Wheel', 2),
(420, 'Window', 6)
Come si può vedere, la parte "Motore" appartiene a entrambi "Chevy" e "Ford" e è elencato due volte con diversi ID. Ancora una volta, questa è una limitazione del design con cui devo convivere.
Ecco ciò che devo realizzare: data una macchina, ho bisogno di trovare tutte le parti per questa macchina e tutte le altre auto a cui queste parti appartengono. Devo continuare a trovare parti e auto in modo ricorsivo fino a raggiungere la fine della catena. La logica può essere delineata come segue: @StartCar -> Parti di una @StartCar -> Altre parti con lo stesso nome -> ottieni Id di quelle "altre" parti -> Ottieni macchine che "possiedono" quelle parti - -> ricomincia e ripeti fino al raggiungimento della fine della catena.
per risolvere il mio problema, ho provato questa query:
DECLARE @StartCar VARCHAR(16) = 'Chevy'
;WITH cte (CarName, PartName)
AS
(
SELECT c.CarName,
cp.PartName
FROM CarPart cp
JOIN Car c ON cp.CarID = c.CarID
WHERE c.CarName = @StartCar
UNION ALL
SELECT c.CarName,
cp.PartName
FROM CarPart cp
JOIN Car c ON cp.CarID = c.CarID
JOIN cte cte ON cp.PartName = cte.PartName
)
SELECT CarName, PartName
FROM cte
Tuttavia, si ottiene in un ciclo infinito e termina. Mi aspetto di vedere l'output simile a questo:
CarName PartName
Chevy Engine
Chevy Door
Ford Engine
Ford Wheel
Toyota Door
Toyota Window
Hugo Window
Apprezzo qualsiasi suggerimento.
Grazie!
+1 per fornire script eseguibili con dati di esempio –