2013-05-09 45 views
5

我在使用普通的旧SQL查询时遇到了一些问题(大多数情况下使用ORM的缺点:))。使用SQL(单独的表)查找具有2个条件的所有行

我有2张表,PRODUCTSRULES。在表RULES我已经定义了产品规则。我想要的是编写一个查询来获得所有已定义规则的产品。

规则由2种方式定义:

  1. 你只能为一个产品指定RULEProductID具有价值,SectorID是NULL)
  2. 您可以使用SectorID更多的是一种产品指定RULEProductID是NULL)

结果需要有规则(product.ID - rule.ProductID)的所有产品,但也包括所有产品ar e在规则表(product.SectorID - rule.SectorID)中的部门中定义。

此外,结果不能有重复的产品(产品其通过在productId定义RULES或通过SectorID

实施例:

PRODUCTS

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 

回答

4

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

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

这*将*可能是最快的(给出相关指标)。将OR分解为两个单独的EXISTS分支可以改善:'WHERE EXISTS(...其中p.ID = r.ProductID)或EXISTS(... WHERE p.SectorID = r.SectorID)' – wildplasser 2013-05-09 21:02:43

+0

@wildplasser只要我可以告诉,[查询被重写为无论如何](http://sqlfiddle.com/#!6/7c91c/2)与下面的连接相同的计划。 – 2013-05-10 16:30:25

2

进行查询和合并结果:

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 

这些可能或可能不产生不同的执行计划。你应该检查,并选择更快的。

+1

在你第一次查询中加入到产品表是没有必要的。只需返回'r.productID'。保存连接总是一件好事;-) – 2013-05-09 21:01:17

+1

和备用将得到重复 – cmd 2013-05-09 21:01:53

+0

@cmd,Declan_K确实;谢谢。 – 2013-05-09 21:03:35

1
select distinct 
     ProductID 
from rules 
where ProductID is not null 
union 
select distinct 
     p.id 
from PRODUCTS p 
inner join 
     RULES r 
on  r.sectorid = p.sectorid 

这里的SQL Fiddle

+1

使用distinct是不必要的。工会的下半年不会返回任何重复。第一个可能,但是联盟会将它们过滤出来,即使重复值不会出现在下半部分。 – 2013-05-09 21:09:09

+0

好点。 另外,我认为约阿希姆的答案比我的好。 – 2013-05-09 21:19:44

3

要获得完整的产品行的配套产品,它是一个简单JOINDISTINCT是必需的,因为产品可能同时符合产品规则和扇区规则,而您只希望它列出一次。

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

An SQLfiddle to test with

0

我相信这样的事情应该工作:

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; 

SQL Fiddle

相关问题