2013-05-09 43 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

相關問題