SQL 搜索具有所有值的项目

问题描述 投票:0回答:1

我在访问数据库中有 3 个表:

Item
(带有
itemId
itemName
),
Recipe
(带有
recipeId
)和
ItemInRecipe
- 其中包含
recipeId
itemId
(项目在食谱中)。 例如:

配方编号 itemId
1 3
1 6
2 6

我想找到包含列表中所有项目的食谱(对于具有 6 作为 itemId 的列表,它将返回 1 和 2)

我尝试使用带有

itemId
的 SQL 查询来完成它:

public static List<int> RecipesWithAllItems(List<int> itemIdList)
{
   List<int> recipeIdList = new List<int>();

   // SQL query that gets the recipe IDs that have all of the items in itemIdList
   string query = string.Format("SELECT recipeId FROM ItemInRecipe WHERE itemId IN " +
   "(SELECT itemId FROM Item WHERE itemId IN (" + string.Join(",", itemIdList) + ")) 
   GROUP BY recipeId HAVING COUNT(itemId) = " + itemIdList.Count);

   DataTable dt = Dbf.GetInfo_fromTable(query); //returns the information as a dataTable

   foreach (DataRow dr in dt.Rows)
   {
      int recipeId = int.Parse(dr["recipeId"].ToString());
      recipeIdList.Add(recipeId);
   }
   return recipeIdList;
}

也尝试过

itemName

public static List<int> GetTheRecipesIdsWithAllItems(List<string> itemList)
{
   List<int> recipeIdList = new List<int>();
            
   // SQL query that gets the recipe IDs that have all of the items in itemList
   string query = string.Format("SELECT recipeId FROM ItemInRecipe WHERE itemId IN " +
   "(SELECT itemId FROM Item WHERE itemName IN (" +
   string.Join(",", itemList.ConvertAll(i => "'" + i + "'")) +
   ")) GROUP BY recipeId HAVING COUNT(itemId) = " + itemList.Count);

   DataTable dt = Dbf.GetInfo_fromTable(query);

   foreach (DataRow dr in dt.Rows)
   {
      int recipeId = int.Parse(dr["recipeId"].ToString());
      recipeIdList.Add(recipeId);
   }
   return recipeIdList;
}

但是,两者都不起作用/返回不正确的结果。 我怎样才能找到包含所有物品的食谱?

c# sql list search
1个回答
0
投票

我建议

group by
加上
having

  select recipeId
group by recipeId
    from ItemInRecipe 
   where itemId in (list items here)
  having count(1) = (list.Count() here)

代码:

public static List<int> RecipesWithAllItems(List<string> itemList) {
  if (itemList is null)
    throw new ArgumentNullException(nameof(itemList));
 
  var ids = itemList
    .Where(item => item != null)
    .Distinct()
// .OrderBy(id => id) // ordering can be helpful if itemList is short
    .ToList();

  //TODO: What should we return in case of empty list?
  if (ids.Count == 0)
    return new List<int>();

  // I've hardcoded ids and ids.Count
  // Since I have to call Dbf.GetInfo_fromTable
  //TODO: Try to parametrize the query  
  var sql = @$"select recipeId
             group by recipeId
                 from ItemInRecipe 
                where itemId in {string.Join(", ", ids)}
               having count(1) = {ids.Count}";

  List<int> recipeIdList = new List<int>();

  DataTable dt = Dbf.GetInfo_fromTable(query);

  foreach (DataRow dr in dt.Rows)
    recipeIdList.Add(Convert.ToInt32(dr["recipeId"]));
  
  return recipeIdList;
}

如果不能使用参数并且

itemList
很短,排序可以帮助优化:你会有更少的不同查询。

© www.soinside.com 2019 - 2024. All rights reserved.