存储过程—在sql中,从一对多表中选择所有fk,其中fk的表数据存在于多个列表/联接中的每个列表/联接中

ttvkxqim  于 2021-07-29  发布在  Java
关注(0)|答案(1)|浏览(336)

我的数据库中有带相关数据的配方(在一系列类别中,每个配方都为每个类别选择了[0-多]个选项)。要搜索配方,用户可以从[0-many]类别中选择[0-many]选项。
我正在尝试构造一个存储过程,该过程返回所有recipeID,这些RecipeID与用户选择了至少一个optionid的每个类别至少一个optionid匹配。
所以-如果你想找到所有主菜和水果甜点,proc需要返回所有recipeids,其中:
在recipedata中,对于具有相同recipeid的所有条目(对于单个配方的所有选项)
至少有一个optionid用于“主菜”或至少有一个optionid用于“甜点”
至少有一个optionid是“水果”
忽略“排名”(用户未选择此类别中的任何选项)
类别的数量是有限和有限的(目前有12个)。现在,我将用户的搜索查询作为12个表变量提供—每个类别一个,列出该类别所选的optionID。我更喜欢将用户的搜索查询作为单个表提交给proc,但我不确定这是否可行。不管怎样,这是一个较低的优先级。
必须可以构造一个查询来返回我要查找的内容,但我不知道如何做到这一点。我所能想到的一切都涉及到在组中循环(每个配方的recipedata、每个类别的选项),据我所知,sql并不是为实现这一点而构建的。
我可以在sql中这样做,还是必须在c代码中这样做?如果我能用sql来做这个-怎么做?
参数:

  1. DECLARE @MealTypeOptionID TABLE ( OptionID INT )
  2. DECLARE @IngredientOptionID TABLE ( OptionID INT )
  3. DECLARE @RankingOptionID TABLE ( OptionID INT )
  4. -- all 'Main Dish' or 'Dessert' recipes that have 'Fruit'
  5. INSERT INTO @MealTypeOptionID (OptionID) VALUES (1), (2)
  6. INSERT INTO @IngredientOptionID (OptionID) VALUES (4)

table:

  1. Recipe
  2. ---------------------------------------------------------------
  3. RecipeID RecipeName
  4. ---------------------------------------------------------------
  5. 1 'Apple Pie'
  6. 2 'Blueberry Ice Cream'
  7. 3 'Brownies'
  8. 4 'Tuna Casserole'
  9. 5 'Pork with Apples'
  10. 6 'Fruit Salad'
  11. Category
  12. ---------------------------------------------------------------
  13. CategoryID CategoryName
  14. ---------------------------------------------------------------
  15. 1 'Meal Type'
  16. 2 'Ingredients'
  17. 3 'Ranking'
  18. Option
  19. ---------------------------------------------------------------
  20. OptionID CategoryID OptionName
  21. ---------------------------------------------------------------
  22. 1 1 'Main Dish'
  23. 2 1 'Dessert'
  24. 3 1 'Side Dish'
  25. 4 2 'Fruit'
  26. 5 2 'Meat'
  27. 6 3 'Meh'
  28. 7 3 'Great'
  29. RecipeData
  30. ---------------------------------------------------------------
  31. RecipeDataID RecipeID OptionID
  32. ---------------------------------------------------------------
  33. 1 1 2
  34. 2 1 4
  35. 3 1 7
  36. 4 2 2
  37. 5 2 4
  38. 6 3 2
  39. 7 4 1
  40. 8 4 5
  41. 9 4 6
  42. 10 5 1
  43. 11 5 4
  44. 12 5 5
  45. 13 6 3
  46. 14 6 4
mbzjlibv

mbzjlibv1#

我的解决方案:

  1. -- @optionsToInclude is a parameter of the proc
  2. DECLARE @optionsToInclude TABLE (CategoryID INT, OptionID INT)
  3. -- result table
  4. DECLARE @recipeIDs TABLE (RecipeID INT)
  5. -- get CategoryID FOR first select
  6. DECLARE @categoryID INT
  7. SELECT TOP 1 @categoryID = CategoryID FROM @optionsToInclude GROUP BY CategoryID
  8. -- insert into result table all RecipeIDs that contain any OptionIDs within CategoryID
  9. INSERT INTO @recipeIDs (RecipeID)
  10. SELECT DISTINCT d.RecipeID
  11. FROM RecipeData d
  12. INNER JOIN @optionsToInclude c
  13. ON c.CategoryID = @categoryID
  14. AND c.OptionID = d.OptionID
  15. -- delete from @optionsToInclude all entries where CategoryID = @categoryID
  16. DELETE FROM @optionsToInclude WHERE CategoryID = @categoryID
  17. -- check if any more Categories exist to loop through
  18. DECLARE @exists BIT = 1
  19. IF (NOT EXISTS (SELECT * FROM @optionsToInclude))
  20. SET @exists = 0
  21. WHILE @exists = 1
  22. BEGIN
  23. -- get CategoryID for select
  24. SELECT TOP 1 @categoryID = CategoryID FROM @optionsToInclude GROUP BY CategoryID
  25. -- delete from result table all RecipeIDs that do not contain any OptionIDs within CategoryID
  26. DELETE FROM @recipeIDs
  27. WHERE RecipeID NOT IN
  28. (
  29. SELECT DISTINCT d.RecipeID
  30. FROM dbo.RecipeData d
  31. INNER JOIN @optionsToInclude i
  32. ON i.CategoryID = @categoryID
  33. AND i.OptionID = d.OptionID
  34. )
  35. -- delete from @optionsToInclude all entries where CategoryID = @categoryID
  36. DELETE FROM @optionsToInclude WHERE CategoryID = @categoryID
  37. -- check if any more Categories exist to loop through
  38. IF (NOT EXISTS (SELECT * FROM @optionsToInclude))
  39. SET @exists = 0
  40. END
展开查看全部

相关问题