2016-05-13 111 views
2

我與動物更新多對多表SQL

CREATE TABLE Animals 
(
AnimalId int NOT NULL, 
Color int NOT NULL, 
Breed int NOT NULL, 
Genre int NOT NULL, 
); 

和表格一模一樣的表,但一切都是可選的(除鍵)

CREATE TABLE Expenses 
(
ExpenseId int NOT NULL, 
Color int, 
Breed int, 
Genre int, 
); 

最後一個不少許多表:

CREATE TABLE AnimalsExpenses 
(
ExpenseId int NOT NULL FOREIGN KEY REFERENCES Expenses(ExpenseId), 
AnimalId int NOT NULL FOREIGN KEY REFERENCES Animals(AnimalId), 
); 

記錄(A,E)應該在桌子上AnimalsExpenses如果

((SELECT Color FROM Animals WHERE AnimalId = a) = (SELECT Color FROM Expenses WHERE ExpenseId = e) 
OR (NULL) = (SELECT Color FROM Expenses WHERE ExpenseId = e)) 
AND 
((SELECT Breed FROM Animals WHERE AnimalId = a) = (SELECT Breed FROM Expenses WHERE ExpenseId = e) 
OR (NULL) = (SELECT Breed FROM Expenses WHERE ExpenseId = e)) 
AND 
((SELECT Genre FROM Animals WHERE AnimalId = a) = (SELECT Genre FROM Expenses WHERE ExpenseId = e) 
OR (NULL) = (SELECT Genre FROM Expenses WHERE ExpenseId = e)) 

...它將如何成爲更新AnimalsExpenses的查詢?那就是:它會刪除不應該是在納米表中的記錄,並補充說,需要在那裏的那些

例子:

------ Animals ------------------- 
AnimalId Color Breed Genre 
---------------------------------- 
    1  1  1  1 
    2  1  1  2 
    3  1  2  2 

----- Expenses ------------------- 
ExpenseId Color Breed Genre 
---------------------------------- 
    1  NULL NULL NULL  (applies to every animal) 
    2  NULL 2  NULL  (applies to animals of breed 2) 
    3   1  2  2  (applies exactly to animal 3) 

----- AnimalsExpenses ------------------------------------------- 
    AnimalId ExpenseId Is it ok? 
----------------------------------------------------------------- 
     1  1   yes, because "expense 1" applies to all 
     2  1   yes, because "expense 1" applies to all 
     3  1   yes, because "expense 1" applies to all 

     1  2   no, breed doesnt match 
     2  2   no, breed doesnt match 
     3  2   yes, because "expense 2" matches breed with "animal 3" 

     1  3   no, breed and genre doesnt match 
     2  3   no, breed doesnt match 
     3  3   yes, everything matches 
+1

您正在使用哪個SQL供應商?我可能會在應用層而不是數據庫中執行此操作。 –

+0

SQL Server。我正在使用LINQ/Entity Framework進行此更新,但速度太慢 – sports

+0

您能否包含一些示例數據並告訴我們允許和禁止的條目是什麼樣子? –

回答

1

你爲什麼不只是截斷表,然後運行

Insert into AnimalsExpenses 
select a.AnimalId 
    , e.ExpenseId 
    from Animals a 
    inner join Expenses e on a.Breed = ISNULL(e.Breed, a.Breed) 
      AND a.Color = ISNULL(e.Color, a.Color) 
      AND a.Genre = ISNULL(e.Genre, a.Genre) 
+0

截斷意味着刪除所有的行?我會嘗試......聽起來很不錯。 1000只動物和20項費用(aprox)的表現如何? – sports

+0

@sports截斷意味着刪除所有行,這是一個命令。不應該太糟糕。順便說一下,我更新了答案,ORs需要是AND – artm

1

我建議你重寫WHERE標準是這樣的:

ISNULL(Expenses.Color, Animals.Color) = Animals.Color 
AND ISNULL(Expenses.Breed, Animals.Breed) = Animals.Breed 
AND ISNULL(Expenses.Genre, Animals.Genre) = Animals.Genre 

請看一下COALESCE