我想查找并删除满足依赖关系的行,但前提是所有兄弟节点都满足该依赖关系。孩子也可以有多个父母,这使得这种毛茸茸但是这里有完整的解释:
我正在开发一个遗留系统,其数据结构非常糟糕,我无从事任何选择。以下是问题的简化,但我认为这是解释问题的最佳方式。
关于我正在做的事情:
在数据库中,我有货运记录A - G
我想删除所有已完成的货件。出货A - E已完成,但不是F或G.
系统中还有几个发票。
规则:
如果已完成的货件是包含未的其他货件的发票的一部分,则无法将其删除
如果已完成的货件是包含其他无法删除的货件的发票的一部分,则无法将其删除
问题:
发票I1包含货件A,B和C.由于这些都已完成,我可以全部删除
发票I2包含货件A,F和G.作为F& G 不已完成,我无法删除
但是,因为A不能被规则1删除,因为它是发票I1的一部分,B或C也不能
...然后我们需要检查任何其他发票B& C是......的一部分。
...等等到无限......
...对于我的生活,我想不出一个简单,快速的SQL语句或算法,而不是通过强力矿石递归 - 直到结束
感激地收到任何其他建议!
答案 0 :(得分:0)
我想我有个主意。假设您从描述中得到类似这三个表的内容(下面的SQL Server语法):
CREATE TABLE Invoice
(
Id INT PRIMARY KEY
)
CREATE TABLE Shipment
(
Id INT PRIMARY KEY,
Completed BIT
)
CREATE TABLE Invoice_Shipment
(
InvoiceId INT FOREIGN KEY REFERENCES Invoice(Id),
ShipmentId INT FOREIGN KEY REFERENCES Shipment(Id)
)
然后你可以:
删除"不必要的"来自Invoice_Shipment
表
从Invoice_Shipment删除 WHERE InvoiceId不在 (从Invoice_Shipment中选择InvoiceId 在哪里ShipmentId IN (SELECT Id FROM Shipment WHERE Completed = 0))
删除"未使用"来自Shipment
表
从货件中删除 WHERE完成= 1并且不在 (从Invoice_Shipment中选择InvoiceId)
重新编写此内容以满足您的需求,并且不要忘记包装交易。
答案 1 :(得分:0)
我尝试过这样的事情 - 这是导致我头疼的递归:
TRUNC Shipments_To_Delete
-- Grab all the 'Complete' Shipments
INSERT INTO Shipments_To_Delete
( SELECT * FROM Shipment WHERE Complete )
-- Make sure we iterate at least once
Shipments_To_Remove = True
WHILE Shipments_To_Remove
-- Test if there's anything left to do..
Shipments_To_Remove =
(
-- Count if there are any Shipments marked for deletion..
-- ..which can't be because they're part of an Invoice..
-- ..which contains *other* Shipments that *can't* be deleted
--
SELECT COUNT(1) FROM Shipments_To_Delete WHERE Shipment_ID IN
-- Find all the Shipments on Invoices that have Shipments that can't be deleted
( SELECT Shipment_ID FROM Invoice_Shipments WHERE Invoice_ID IN
-- Find all the Invoices that have Shipments which can't be deleted
( SELECT Invoice_ID FROM Invoice_Shipments WHERE Shipment_ID NOT IN
( SELECT Shipment_ID FROM Shipments_To_Delete )
)
)
) > 0
IF Shipments_To_Remove THEN
-- Reuse the query above to make it a DELETE
--
DELETE FROM Shipments_To_Delete WHERE Shipment_ID IN
( SELECT Shipment_ID FROM Invoice_Shipments WHERE Invoice_ID IN
( SELECT Invoice_ID FROM Invoice_Shipments WHERE Shipment_ID NOT IN
( SELECT Shipment_ID FROM Shipments_To_Delete )
)
)
ENDIF
-- If we've changed anything, loop around again and check whether there's anything left to do
DO