2012-09-25 102 views
2

我有3個表:SQL Server 2008中,如何檢查是否在數據庫中存在多條記錄?

  • 配方:
    • ID,名稱
  • 成分:
    • ID,名稱
  • recipeingredient:
    • ID,recipeId,ingredientId,數量

每一次,客戶創建一個新的配方,我需要檢查recipeingredient表來驗證這個方子存在與否。如果ingredientIdquantity是完全一樣的,我會告訴配方已經存在的客戶。由於我需要檢查多行,需要幫助來編寫此查詢。

+2

你怎麼代表了新的配方?它是在同一張表中,在臨時表中還是在內存中? –

+0

@ GordonLinoff我假設這是一個表單發佈......但很好的問題。 – RedFilter

+0

是的,這是一個表格帖子 – qinking126

回答

2

瞭解您的成分和數量,你可以做這樣的事情:

select recipeId as ExistingRecipeID 
from recipeingredient 
where (ingredientId = 1 and quantity = 1) 
    or (ingredientId = 8 and quantity = 1) 
    or (ingredientId = 13 and quantity = 1) 
group by recipeId 
having count(*) = 3 --must match # of ingeredients in WHERE clause 
2

我原本以爲下面的查詢將查找菜譜的對,具有完全相同的成分:

select ri1.recipeId, ri2.recipeId 
from RecipeIngredient ri1 full outer join 
    RecipeIngredient ri2 
    on ri1.ingredientId = ri2.ingredientId and 
     ri1.quantity = ri2.quantity and 
     ri1.recipeId < ri2.recipeId 
group by ri1.recipeId, ri2.recipeId 
having count(ri1.id) = count(ri2.id) and -- same number of ingredients 
     count(ri1.id) = count(*) and  -- all r1 ingredients are present 
     count(*) = count(ri2.id)   -- all r2 ingredents are present 

但是,此查詢不準確計數的事情,因爲不匹配沒有正確的成對的ID。唉。

以下確實做正確的比較。它會在連接之前統計每個配方中的成分,因此只能在所有匹配的行上比較此值。

select ri1.recipeId, ri2.recipeId 
from (select ri.*, COUNT(*) over (partition by recipeid) as numingredients 
     from @RecipeIngredient ri 
    ) ri1 full outer join 
    (select ri.*, COUNT(*) over (partition by recipeid) as numingredients 
     from @RecipeIngredient ri 
    ) ri2 
    on ri1.ingredientId = ri2.ingredientId and 
     ri1.quantity = ri2.quantity and 
     ri1.recipeId < ri2.recipeId 
group by ri1.recipeId, ri2.recipeId 
having max(ri1.numingredients) = max(ri2.numingredients) and 
     max(ri1.numingredients) = count(*) 

having子句保證每個配方,相同的許多成分,而匹配的成分的數量爲總。這個時候,我已經測試了以下數據:

insert into @recipeingredient select 1, 1, 1 
insert into @recipeingredient select 1, 2, 10 
insert into @recipeingredient select 2, 1, 1 
insert into @recipeingredient select 2, 2, 10 
insert into @recipeingredient select 2, 3, 10 
insert into @recipeingredient select 3, 1, 1 
insert into @recipeingredient select 4, 1, 1 
insert into @recipeingredient select 4, 3, 10 
insert into @recipeingredient select 5, 1, 1 
insert into @recipeingredient select 5, 2, 10 

如果你有一個新的配方,你可以修改這個查詢只尋找配方中的一個表(比如RI1)使用附加條件在on條款。

如果將食材在一個臨時表中,可以替代這些表中的一個,說RI1,新表。

+0

經過測試,我無法讓它工作。 –

+0

@TimLehner。 。 。你能詳細說明數據的錯誤還是問題? –

+0

當然,只要用我的答案數據(與您的方向基本相同)進行試用即可。然後更改數量。或者添加/刪除一行。你的'group by'可能實際上掩蓋了食譜之間的差異。 –

0

你可以嘗試這樣的事情找到,如果你有一個重複:

-- Setup test data 
declare @recipeingredient table (
     id int not null primary key identity 
    , recipeId int not null 
    , ingredientId int not null 
    , quantity int not null 
) 
insert into @recipeingredient select 1, 1, 1 
insert into @recipeingredient select 1, 2, 10 
insert into @recipeingredient select 2, 1, 1 
insert into @recipeingredient select 2, 2, 10 

-- Actual Query 
if exists (
    select * 
    from @recipeingredient old 
     full outer join @recipeingredient new 
      on old.recipeId != new.recipeId   -- Different recipes 
      and old.ingredientId = new.ingredientId -- but same ingredients 
      and old.quantity = new.quantity   -- and same quantities 
    where old.id is null -- Match not found 
     or new.id is null -- Match not found 
) 
begin 
    select cast(0 as bit) as IsDuplicateRecipe 
end 
else begin 
    select cast(1 as bit) as IsDuplicateRecipe 
end 

由於這是真的只是一個重複的搜索,您可能要替換一個臨時表或pass a table variable的「新」表。這樣,您在搜索之前不必插入新記錄。您也可以插入基表中,根據結果將所有內容包含在事務中並進行回滾。

相關問題