2012-05-18 50 views
0

我有3個表格:Products,ProductProperties,Properties。我需要獲得所有沒有「物業B」的產品。表:獲取沒有連接的記錄

# Products   # Join table     # Properties 
+----+-----------+ +------------+-------------+ +-------------+---------------+ 
| id | name  | | product_id | property_id | | property_id | property_name | 
+----+-----------+ +------------+-------------+ +-------------+---------------+ 
| 1 | Product 1 | |   1 |   1 | |   1 | Propeprty A | 
| 2 | Product 2 | |   1 |   2 | |   2 | Propeprty B | 
| 3 | Product 3 | |   2 |   1 | +-------------+---------------+ 
+----+-----------+ |   2 |   2 | 
        |   3 |   1 | 
        +------------+-------------+ 

在這種特殊情況下我希望產品3要返回

是否有可能在單個數據庫查詢中獲得所有必需的產品?什麼最小的查詢可能實現呢?

編輯。考慮子查詢的查詢不好

回答

0

好像你想要一個OUTER JOIN,然後一個WHERE帶來子句後面的非匹配屬性。這是未經測試,但:

SELECT Products.* FROM 
Products RIGHT OUTER JOIN Join_Table 
    ON Products.ID = Join_Table.Product_ID 
    AND Join_Table.Property_ID = 2 
WHERE Products.ID IS NULL 
+0

這只是簡單的'ol不會工作。產品。ID永遠不會是NULL - 因爲這是FROM子句所在的表,並且沒有RIGHT/FULL連接。 –

+0

馬克,你說得對。 Lester的答案有一個錯誤:在第5行應該是'Join_Table.Property_ID'而不是'Products.ID'。 – gmile

+0

是的,我想我當然是指右連接,但我最好在編輯之前再次瀏覽一遍。 – LesterDove

1
select * from Products P where not exists (select * from ProductProperties 
inner join Properties on ProductProperties .property_id = Properties property_id 
where P.product_id = ProductProperties.product_id and property_name = 'Propeprty B') -- *or whatever* 
+0

我想這是行不通的。該查詢將返回空結果集。 –

+0

謝謝你的回答,但我暗示不要再做子查詢。 – gmile

+0

我只是編輯我的答案。我認爲現在是正確的。 –

0
SELECT Products.ProductID, Products.Name, Properties.property_name FROM Products 
INNER JOIN ProductProperties ON Products.product_ID = ProductProperties.product_ID 
INNER JOIN Properties ON ProductProperties.Property_ID = Properties.Property_ID 
WHERE Properties.Property_ID <> 2 
+0

這將返回具有* PropertyB的產品的非PropertyB屬性。 –

+0

你說得對,我正在打字的速度。你應該'LEFT OUTER JOIN屬性ON ProductProperties.Property_ID = Properties.Property_ID' – Phoenix

-1

是(修正去除潛艇),

Select * from 
    Products pr 
    left join jointable jt on pr.id = jt.product_id 
    join properties pr on jt.property_id = pr.property_id and pr.property_name = 'Property B' 
where jt.product_id is null 
+0

謝謝你的回答,但我暗示不要做子查詢也。 – gmile

+0

我認爲你的<>在where子句中需要= =。否則,您將返回* do *具有PropertyB的產品。 –

1

我需要把所有的產品,不具有 「物業B」

逆問題。找到PropertyB,然後否定它。

開始與所有PropertyB屬性:

SELECT 
    Property_Id 
FROM Properties 
WHERE 
    Property_Name = 'Property B' 

然後,找到ProductId s表示有那些Property_Id S:

SELECT 
    ProductId 
FROM ProductProperties 
JOIN (
    --1st query 
    SELECT 
     Property_Id 
    FROM Properties 
    WHERE 
     Property_Name = 'Property B' 
) as PropertyB ON 
    ProductProperties.Property_Id = PropertyB.Property_Id 

然後,找到所有的Product不是該集合:

SELECT 
    ProductId 
FROM Product 
LEFT OUTER JOIN (
    --2nd query 
    SELECT 
     ProductId 
    FROM ProductProperties 
    JOIN (
     --1st query 
     SELECT 
      Property_Id 
     FROM Properties 
     WHERE 
      Property_Name = 'Property B' 
    ) as PropertyB ON 
     ProductProperties.Property_Id = PropertyB.Property_Id 
) as ProductsWithPropertyB ON 
    Products.ProductId = ProductsWithPropertyB.ProductId 
WHERE 
    ProductsWithPropertyB.ProductId IS NULL 

然後,您可以簡化一下:

SELECT 
    ProductId 
FROM Product 
LEFT OUTER JOIN (
    SELECT 
     ProductId 
    FROM ProductProperties 
    JOIN Properties ON 
     ProductProperties.PropertyId = Properties.PropertyId 
    WHERE 
     Properties.Name = 'Property B' 
) as ProductsWithPropertyB ON 
    Products.ProductId = ProductsWithPropertyB.ProductId 
WHERE 
    ProductsWithPropertyB.ProductId IS NULL 

或者,如果你喜歡IN條款(服務器可能不關心):

SELECT 
    ProductId 
FROM Products 
WHERE 
    ProductId NOT IN (
      SELECT ProductId FROM ProductProperties WHERE PropertyId IN (
       SELECT PropertyId FROM Properties WHERE PropertyName = 'Property B' 
     ) 
    ) 
+0

我最初是這樣做的,但我想避免使用子查詢來提高效率。 – gmile

+1

你有3個信息表。你不會比3表連接(或等價的IN子句)更有效率。你想要避免的是相關*子查詢(每個結果集行只運行一次) - 根本不是子查詢。 –

+0

謝謝你的幫助,馬克。我現在將明確區分相關的子查詢。然而,似乎@LesterDove對我來說工作正常 – gmile