【问题标题】:A complex SQL Query string inner join common denominator一个复杂的 SQL Query 字符串内连接公分母
【发布时间】:2009-08-31 12:56:23
【问题描述】:

这是一个非常重要的 sql 查询,我的整个网站都以此为基础..

它不工作..

没有例子很难解释..

有 2 个表,一个是 IngredientsTable,另一个是 ProductsTable。

IngredentsTable 我有以下内容

  1. 面包
  2. 鸡胸肉
  3. 面条
  4. 蛋黄酱
  5. 奶酪
  6. 番茄酱
  7. 黄油

还有ProductsTable

  1. Spageti
  2. 鸡胸肉三明治

还有一个连接两个表的映射表。它有 IngredientID 和 ProductID

现在,映射表 鸡胸肉三明治 - 面包

鸡胸肉三明治 - 蛋黄酱

鸡胸肉三明治 - 奶酪

鸡胸肉三明治 - 番茄酱

Spageti --- 面条

意大利面——奶酪

Spageti --- 番茄酱

你会注意到 Cheese 和 Ketchup 是 Chicken Breast 和 Spageti 的常见条目

我想编写一个 sql 查询来获取具有指定成分的产品的 ID。

我可以通过以下查询部分实现它

SELECT 
  ProductTable.id,
  ProductTable.Name 
FROM ProductTable 
INNER JOIN MappingTable 
  ON ProductTable.id = MappingTable.ProductID
WHERE MappingTable.IngredientID =  5; 

假设 5 是奶酪,我成功地获得了鸡胸肉三明治和意大利面的结果

但如果我再添加一个,WHERE MappingTable.IngredientID = 5,6; 6 是面包,它应该只显示一个鸡胸肉三明治而不是 Spageti

我收到错误 "," 语法.. 甚至 "and" 也没有得到结果。

如何检查多个成分,例如 WHERE MappingTable.IngredientID = 5,6,7;

非常感谢任何帮助!!!

我需要在一个查询中拥有这个..

请告诉我选项

【问题讨论】:

    标签: sql inner-join


    【解决方案1】:

    通过 2 个查询,您可以使用结果的交集

    但是你说你想要在一个查询中。

    一个近似值是按语句分组并计算从结果中收到的行数。它必须等于您的成分的数量。但是,如果您的成分在同一产品中重复多次,它将不起作用。

    2 个成分 ID 的类似内容:

    SELECT ProductTable.id, ProductTable.Name FROM ProductTable 
    INNER JOIN MappingTable ON ProductTable.id = MappingTable.ProductID 
    WHERE MappingTable.IngredientID in (5,6) group by ProductTable.id, ProductTable.Name 
    HAVING count(*) = 2;
    

    【讨论】:

      【解决方案2】:
      WHERE MappingTable.IngredientID IN (5, 6, 7)
      

      对不起,我的错。这个怎么样?:

      SELECT 
        p.id,
        p.Name 
      FROM ProductTable p
      INNER JOIN (SELECT * FROM MappingTable WHERE IngredientID IN (5, 6, 7)) m
        ON p.id = m.ProductID
      

      【讨论】:

      • 我不这么认为...有了这个,任何具有 5 或 6 的产品都会通过,而不是同时具有 5 和 6 的产品
      【解决方案3】:

      首先,编辑您的问题,使示例表中的数据与示例问题相匹配...如果 5 是奶酪,6 是面包,则使成分表与之匹配。否则会令人困惑。

      其次,你说“,它应该只给我一个鸡胸肉三明治而不是意大利面”让我觉得你想知道有所有列出的 ingfrediants 的产品,而不是任何一个。如果是这样,那么你想要以下

        Select P.id,  P.Name 
        FROM ProductTable P 
        Where Exists (Select * From Mapping Table
                      Where ProductId = P.ProductId
                          And IngredientId = 5)
          And Exists (Select * From Mapping Table
                      Where ProductId = P.ProductId
                          And IngredientId = 6)
          And Exists (Select * From Mapping Table
                      Where ProductId = P.ProductId
                          And IngredientId = 7)
      

      或者,使用计数逻辑:

         Select P.id,  P.Name 
         From ProductTable P 
         Where (Select Count(Distinct IngredientId)
                From MappingTable M
                Where ProductId = P.ProductId 
                  And IngredientId In (5,6,7)) = 3
      

      【讨论】:

      • 编辑了问题,你明白了,它在第一个查询中效果很好,虽然不是反向逻辑
      【解决方案4】:

      您需要为每种成分单独链接到映射表:

      SELECT 
        ProductTable.id,
        ProductTable.Name 
      FROM ProductTable 
      INNER JOIN MappingTable AS MappingTable1
        ON ProductTable.id = MappingTable1.ProductID
        AND MappingTable1.IngredientID = 5
      INNER JOIN MappingTable AS MappingTable2
        ON ProductTable.id = MappingTable2.ProductID
        AND MappingTable2.IngredientID = 6
      

      如果您按照其他发帖人的建议使用 IN 运算符,您将获得用于面包和奶酪的意大利面条和鸡肉三明治,因为 IN 本质上是一个 OR 类型的查询。

      【讨论】:

        【解决方案5】:

        这应该可行,尽管您需要为其提供两个“变量” - 第一个是以逗号分隔的成分 ID 集,第二个 (@IngredientsCount) 是该列表中成分的数量。

        SELECT ProductsTable.id, ProductTable.Name
        FROM ProductsTable
        INNER JOIN (SELECT ProductID, Count(*) AS Ingredients
            FROM MappingTable
            WHERE IngredientID IN (...ids of ingredients here...)
            GROUP BY ProductID
            HAVING Count(*) = @IngredientsCount) AS ProductIngredients ON ProductsTable.ProductID = ProductIngredients.ProductID
        

        如果同一成分可能被记录两次(尽管您的表结构看起来不允许这样做,而且可能没有必要),请将两个 Count(*) 切换为 Count(Distinct IngredientID) 并更改@IngredientCount 是使用的不同成分的数量。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-19
          • 2015-09-18
          • 1970-01-01
          • 2012-01-28
          • 1970-01-01
          • 2015-10-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多