2013-04-08 27 views
0

選擇我有三個獨立的表 - pagestags,並pages_tagged - 包含頁面內容標籤名稱IDS,並頁IDS標籤ID分別。磕磕絆絆與加盟,並從單獨的表

我試圖建立一個MySQL查詢需要的搜索項,檢查現有的標籤,找到匹配的標籤ID,並返回與所述標籤的所有網頁 - 我這有運作良好。但是,當我試圖進一步擴展它以查詢頁表的標題列中的匹配字符串時,事情有點過度了。

我的SQL如下:

SELECT tags.id, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
     DATE_FORMAT(pages.dateAdded, '%M %e, %Y') AS dateAdded, 
     pages.viewcount, pages.sessionId 
FROM tags JOIN pages_tagged ON tags.id = pages_tagged.tag_id 
JOIN pages ON pages_tagged.page_id = pages.randomId 
WHERE (tags.tag = 'ovechkin' OR pages.title LIKE '%ovechkin%') 
ORDER BY dateAdded DESC 

我知道這裏的操作順序是非常錯誤的,但我不能換我的頭周圍正確的方法來修改這個查詢,使之正常工作。

會有人能夠指出我的明顯的錯誤?

編輯:

爲了澄清「肚了,」當運行查詢,它的「成功」。但是,不會返回任何行。

修改WHERE子句如下隔離pages.title LIKE「%奧韋奇金%」從未導致返回的行,不管搜索詞是什麼。

WHERE (pages.title LIKE '%ovechkin%') 

編輯2:

樣品下面的數據。

pages 
╔════╦════════════════════════╦═════════════════════╦══════════╦═══════════╗ 
║ id ║   title   ║  dateAdded  ║ randomId ║ viewcount ║ 
╠════╬════════════════════════╬═════════════════════╬══════════╬═══════════╣ 
║ 57 ║ Ovechkin looping about ║ 2013-04-07 19:26:06 ║ xp3rvju ║   5 ║ 
╚════╩════════════════════════╩═════════════════════╩══════════╩═══════════╝ 

tags 
╔════════╦══════════╗ 
║ id  ║ tag  ║ 
╠════════╬══════════╣ 
║  25 ║ ovechkin ║ 
╚════════╩══════════╝ 

pages_tagged 
╔══════════════════╗ 
║ tag_id | page_id ║ 
╠══════════════════╣ 
║ 25 | xp3rvju  ║ 
║ 25 | mpbjbk6  ║ 
╚══════════════════╝ 

編輯3:

作爲建議,一個RIGHT JOIN得到pages.title工作。修改後的查詢是:

SELECT tags.id, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
    DATE_FORMAT(pages.dateAdded, '%M %e, %Y') AS dateAdded, 
    pages.viewcount, pages.sessionId 
FROM tags RIGHT JOIN pages_tagged ON tags.id = pages_tagged.tag_id 
RIGHT JOIN pages ON pages_tagged.page_id = pages.randomId 
WHERE (tags.tag = 'ovechkin' OR pages.title LIKE '%ovechkin%') 
ORDER BY dateAdded DESC  

還有一個問題是,如果頁面在其標題和相關標籤中都有相同的搜索詞,它將返回兩次。我試圖修改它以包括在選擇DISTINCT,如下,但這並不會對返回行的影響。

SELECT DISTINCT tags.id, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
    DATE_FORMAT(pages.dateAdded, '%M %e, %Y') AS dateAdded, 

編輯4:

不妨包含最終溶液,以防止重複 - GROUP BY

SELECT tags.id, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
    DATE_FORMAT(pages.dateAdded, '%M %e, %Y') AS dateAdded, 
    pages.viewcount, pages.sessionId 
FROM pages 
LEFT JOIN pages_tagged ON pages.randomId = pages_tagged.page_id 
LEFT JOIN tags ON tags.id = pages_tagged.tag_id 
WHERE (tags.tag = 'ovechkin' OR pages.title LIKE '%ovechkin%') 
GROUP BY pages.randomId 
ORDER BY dateAdded DESC  
+0

你能解釋一下「事情有點過度了嗎」 - 你看到的結果與你期望看到的結果相反嗎? (FWIW,現有的查詢看起來OK。) – 2013-04-08 15:13:45

+0

當然! 查詢運行「成功」,但沒有結果實際返回。移除tags.tag ='thang'沒有任何影響,但無論pages.title LIKE'%term%'下面的搜索字詞是什麼,都不會返回任何行。 – kaput 2013-04-08 15:17:37

+0

你可以發佈一些相關的樣本數據嗎? – 2013-04-08 15:19:15

回答

0

,以瞭解如何在一般加入工作,這裏是一個簡單的解釋是很重要的:http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

既然你正在尋找一個標籤OR在標題比賽,我猜你想使用該關係爲RIGHT JOIN,因爲此查詢不會返回任何未加標籤的頁面。

當前,如果您的頁面標題爲ovechkin,但沒有標籤,則不會使用此查詢找到它。

這是我的嘗試:http://sqlfiddle.com/#!2/c25c5/2

一般情況下,查詢是建立你所得到的所有標籤,然後加入任何標記網頁的手段的方式。沒有WHERE子句的行爲如下:

執行正常的JOIN只會返回帶標籤的頁面,如果數據庫中沒有標籤,您將不會獲得單行。

使用LEFT JOIN表示您會得到每個標籤的結果,即使沒有標籤頁也是如此。

使用RIGHT JOIN表示您將獲得所有頁面的所有結果行,即使沒有標籤,或者沒有頁面被標記。

對於所有這些,沒有數據的任何字段都將填充null。

我會建議更改查詢到這個(爲便於閱讀,刪除某些字段):

SELECT tags.id, pages_tagged.page_id, pages.id, pages.randomId 
FROM pages 
LEFT JOIN pages_tagged ON pages.randomId = pages_tagged.page_id 
LEFT JOIN tags ON tags.id = pages_tagged.tag_id 

WHERE (tags.tag = 'ovechkin' OR pages.title LIKE '%ovechkin%') 

你會得到相同的頁面超過一次,如果它有不止一個標籤。

+0

這很好知道 - 我沒有意識到這會發生。我會看看是否有什麼區別.. – kaput 2013-04-08 15:50:09

+0

更正,查詢的方式現在應該是一個正確的加入,我編輯了答案 – gordonk 2013-04-08 15:51:58

+0

正如您所說明的正確加入使這項工作!看起來像一個簡單的修復。這就是說,我似乎遇到了第二個問題,如果頁面在標籤和標題中都有搜索詞,它將被返回兩次 - 是否有辦法防止重複? – kaput 2013-04-08 16:01:21

0

嘗試以下操作:

select * from 
    (SELECT tags.id as tid, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
      DATE_FORMAT(pages.dateAdded, '%M %e, %Y') AS dateAdded, 
      pages.viewcount, pages.sessionId 
    FROM tags JOIN pages_tagged ON tags.id = pages_tagged.tag_id 
    JOIN pages ON pages_tagged.page_id = pages.randomId 
    WHERE tags.tag = 'thang' 
    union 
    (SELECT tags.id as tid, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
      DATE_FORMAT(pages.dateAdded, '%M %e, %Y') AS dateAdded, 
      pages.viewcount, pages.sessionId 
    FROM pages JOIN pages_tagged on pages_tagged.page_id = pages.randomId 
    JOIN tags ON tags.id = pages_tagged.tag_id 
    WHERE   pages.title LIKE '%thang%' 
    ) 
) as a 
    ORDER BY a.dateAdded DESC 

這樣以後 「正確」 的頁面會選擇第一個 「正確」 的標籤。

+0

你爲什麼不堅持左連接?我認爲這已經足夠 – gordonk 2013-04-08 15:28:58

+0

我改變了答案。 Tr這個變種。 – arheops 2013-04-08 15:30:09

+0

我似乎正在用'重複列名'id'' - 但我不完全確定它來自哪裏。 – kaput 2013-04-08 15:46:39