代码之家  ›  专栏  ›  技术社区  ›  Jamo

SQL问题:排除记录

  •  2
  • Jamo  · 技术社区  · 16 年前

    我有一个数据库(NexusDB(据称符合SQL-92)),其中包含and Item表、Category表和多对多ItemCategory表,后者只是一对键。正如您所料,项目被分配到多个类别。

    我希望所有最终用户选择以下所有项目

    项目ID |类别ID
    --------------------------------
    01 | 01
    01 | 02
    01 | 12

    02 | 01
    02 | 02
    02 | 47

    03 | 01
    03 | 02
    03 | 14
    等。。。

    我希望能够选择分配给类别X、Y和Z但未分配给类别P和Q的所有ItemID。

    例如,对于上面的示例数据,假设我想抓取分配给类别01或02但不是12的所有项目(产生项目02和03)。大致如下:

    选择项目ID的位置(类别ID IN(01,02))

    …并从该集合中删除SELECT ItemID WHERE NOT(CategoryID=12)

    这可能是一个非常基本的SQL问题,但目前它让我很困惑。感谢任何帮助。

    4 回复  |  直到 13 年前
        1
  •  2
  •   Tom    16 年前

    你可以试试,除了

    SELECT ItemID FROM Table
    EXCEPT
    SELECT ItemID FROM Table
    WHERE
    CategoryID <> 12
    
        2
  •  2
  •   Bill Karwin    16 年前

    我希望能够选择全部 分配给的项目ID X、Y和Z类,但不是 分配到P类和Q类。

    我无法从NexusDB文档中确认 SELECT 它们支持子查询,但它们确实支持LEFT OUTER JOIN和GROUP BY。因此,这里有一个在这些限制范围内工作的查询:

    SELECT i1.ItemID
    FROM ItemCategory i1
      LEFT OUTER JOIN ItemCategory i2
        ON (i1.ItemID = i2.ItemID AND i2.CategoryID IN ('P', 'Q'))
    WHERE i1.CategoryID IN ('X', 'Y', 'Z')
      AND i2.ItemID IS NULL
    GROUP BY i1.ItemID
    HAVING COUNT(i1.CategoryID) = 3;
    
        3
  •  1
  •   Gustavo Rubio    16 年前
    SELECT i.ItemID, ic.CategoryID FROM Item AS i
    INNER JOIN ItemCategory ic
    ON i.ItemID = ic.ItemID
    WHERE ic.CategoryId = 1 OR ic.CategoryId = 2
    

    当然,你需要在WHERE子句中加入你想得到的类别。

        4
  •  0
  •   Tom H zenazn    16 年前

    对于类别数量较少且已知的简单情况,您可以简单地使用几个连接来检查是否存在:

    SELECT
         ItemID
    FROM
         Items I
    INNER JOIN ItemCategories IC1 ON IC1.ItemID = I.ItemID AND IC1.CategoryID = '01'
    INNER JOIN ItemCategories IC2 ON IC2.ItemID = I.ItemID AND IC2.CategoryID = '02'
    LEFT OUTER JOIN ItemCategories IC3 ON IC3.ItemID = I.ItemID AND IC3.CategoryID = '12'
    WHERE IC3.ItemID IS NULL
    

    对于更一般的情况,给定匹配和不匹配列表中未知数量的项目,您可以使用以下查询。我为每个列表使用了一个表变量(在SQL Server中可用),但您可以根据需要对实际表或变量/参数列表使用select。想法保持不变:

    SELECT
         ItemID
    FROM
         Items I
    WHERE
         (
          SELECT COUNT(*)
          FROM ItemCategories IC1
          WHERE IC1.ItemID = I.ItemID
            AND IC.CategoryID IN
               (SELECT CategoryID FROM @MustHaves)
          ) = (SELECT COUNT(*) FROM @MustHaves) AND
          (
          SELECT COUNT(*)
          FROM ItemCategories IC1
          WHERE IC1.ItemID = I.ItemID
            AND IC.CategoryID IN
               (SELECT COUNT(*) FROM @MustNotHaves)
          ) = 0
    
    推荐文章