2016-05-13 72 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