2011-02-09 55 views
0

我有兩個表這樣的下面,MySQL:選擇未被標記的頁面?

頁表

pg_id title 
1  a 
2  b 
3  c 
4  d 

標記表中的分貝

tagged_id pg_id 
1   1 
2   4 

我要選擇這些標籤的頁面,我嘗試用下面的查詢但不起作用,

SELECT * 
FROM root_pages 
LEFT JOIN root_tagged ON (root_tagged.pg_id = root_pages.pg_id) 
WHERE root_pages.pg_id != root_tagged.pg_id 

它返回零 - Showing rows 0 - 1 (2 total, Query took 0.0021 sec)

但我想它返回

pg_id title 
    2  b 
    3  c 

我的查詢一定是錯了嗎?
如何返回未正確標記的頁面?

回答

2
SELECT * 
FROM root_pages 
LEFT JOIN root_tagged ON root_tagged.pg_id = root_pages.pg_id 
WHERE root_tagged.pg_id IS NULL 

!=(或<>)運算符比較兩個值,但不能被用於NULL。

  • NULL = NULL返回false
  • NULL = 0返回false
  • NULL!= NULL返回false

你明白了吧,要檢查是否爲NULL應該使用IS或IS NOT運算符。

1

如果密度標記在頁面超過2:1左右,那麼使用NOT EXISTS會比使用LEFT JOIN +更快IS NULL

SELECT * 
FROM root_pages 
WHERE NOT EXISTS (
    SELECT * 
    FROM root_tagged 
    WHERE root_tagged.pg_id = root_pages.pg_id) 

這是可選的更清楚,陳述你正在尋找什麼,不存在。

對於三振文本以上:
問題是MySQL的特異性的,並假設root_tagged.pg_id不能爲空,LEFT JOIN + IS NULL使用被實現反連接其是相同的策略NOT EXISTS,除非NOT EXISTS添加了一些開銷,所以LEFT JOIN應該工作得更快。

+0

我同意它更清楚,但它通常使用NOT EXISTS的速度較慢(在MySQL中,並非一般)。如果你這樣做,你最好選擇一個字段或一個常量值而不是`*`。 – GolezTrol 2011-02-09 23:33:59