使用SQL查找具有2个条件的所有行(单独的表)

使用SQL查找具有2个条件的所有行(单独的表),sql,Sql,我在使用普通的SQL查询时遇到了一些问题(大部分时间使用ORMs的缺点:)) 我有两个表,产品和规则。在表RULES中,我定义了产品的规则。我想要的是编写一个查询,以获取所有已定义规则的产品 规则有两种定义方式: 您只能为一个产品指定规则(ProductID有值,SectorID为空) 您可以使用SectorID(ProductID为空)为多个产品指定规则 结果需要包含所有具有规则的产品(product.ID-rule.ProductID),以及在规则表中的扇区中定义的所有产品(product.

我在使用普通的SQL查询时遇到了一些问题(大部分时间使用ORMs的缺点:))

我有两个表,
产品
规则
。在表
RULES
中,我定义了产品的规则。我想要的是编写一个查询,以获取所有已定义规则的产品

规则有两种定义方式:

  • 您只能为一个产品指定
    规则
    ProductID
    有值,
    SectorID
    为空)
  • 您可以使用
    SectorID
    ProductID
    为空)为多个产品指定
    规则
  • 结果需要包含所有具有规则的产品(
    product.ID-rule.ProductID
    ),以及在规则表中的扇区中定义的所有产品(
    product.SectorID-rule.SectorID

    此外,结果不能有重复的产品(由
    规则中的
    productId
    SectorID
    定义的产品)

    例如:

    产品

    ID  SectorID
    1   1
    2   1
    3   1
    4   2
    5   3
    6   3
    
    ID ProductID SectorID
    1  1         NULL
    4  NULL      1
    5  6         NULL
    
    规则

    ID  SectorID
    1   1
    2   1
    3   1
    4   2
    5   3
    6   3
    
    ID ProductID SectorID
    1  1         NULL
    4  NULL      1
    5  6         NULL
    
    预期结果

    PRODUCTS with IDs : 1, 2, 3, 6
    

    执行两个查询并合并结果:

    SELECT ProductID FROM Rules
    WHERE ProductID IS NOT NULL
    UNION
    SELECT p.ID FROM Product p 
    INNER JOIN Rules r ON p.SectorID = r.SectorID
    
    工会将过滤掉重复的ID。假设您的示例已简化,您可以将其用作子查询,以获取具有规则的所有产品的列表,并使用该列表与其他表关联以返回所需的数据

    另一种办法:

    SELECT DISTINCT p.ID FROM Product p 
    INNER JOIN Rules r 
    ON p.ID = r.ProductID OR p.SectorID = r.SectorID
    

    这些可能会也可能不会生成不同的执行计划。你应该检查一下,然后选择更快的。

    我能想到的最简单的方法,但不一定是最快的

    SELECT * FROM products AS p WHERE
           EXISTS (SELECT * FROM rules AS r WHERE p.ID = r.ProductID OR p.SectorID = r.SectorID)
    

    下面是要获得匹配产品的完整产品行的

    ,它是一个简单的
    连接
    。由于产品可能同时匹配产品规则和行业规则,并且您只希望它列出一次,因此需要使用
    DISTINCT

    SELECT DISTINCT p.* 
    FROM products p
    JOIN rules r
      ON p.ID       = r.ProductID
      OR p.SectorID = r.SectorID
    

    .

    我相信这样的方法应该有效:

    SELECT DISTINCT p.id 
    FROM Products p
    LEFT JOIN Rules r1 ON p.id = r1.productID
    LEFT JOIN Rules r2 ON p.SectorID = r2.SectorID
    WHERE r1.id IS NOT NULL OR r2.SectorID IS NOT NULL 
    ORDER BY p.id;
    

    在第一次查询中,不需要连接到product表。只需返回
    r.productID
    。保存加入总是一件好事;-)而候补者将得到重复这可能是最快的(考虑到相关的索引)。将OR拆分为两个独立的EXISTS分支可以改善情况:
    WHERE EXISTS(…其中p.ID=r.ProductID)或EXISTS(…其中p.SectorID=r.SectorID)
    @wildplasser,与下面的联接计划相同。不需要使用distinct。工会的后半部分不会返回任何副本。第一个可能是,但是联合会过滤掉它们,即使重复的值没有出现在下半部分。这一点很好。而且,我认为约阿希姆的答案比我的好。