2017-06-08 197 views
0

這裏是我的表結構:如何選擇所有包含特定標籤的帖子?

// posts 
+----+-----------+---------------------+-------------+ 
| id | title |  body   | keywords | 
+----+-----------+---------------------+-------------+ 
| 1 | title1 | Something here  | php,oop  | 
| 2 | title2 | Something else  | html,css,js | 
+----+-----------+---------------------+-------------+ 

// tags 
+----+----------+ 
| id | name | 
+----+----------+ 
| 1 | php  | 
| 2 | oop  | 
| 3 | html  | 
| 4 | css  | 
| 5 | js  | 
+----+----------+ 

// pivot 
+---------+--------+ 
| post_id | tag_id | 
+---------+--------+ 
| 1  | 1  | 
| 1  | 2  | 
| 2  | 3  | 
| 2  | 4  | 
| 2  | 5  | 
+---------+--------+ 

好的,那我有兩個標籤(phphtml),我需要選擇標有他們的所有帖子。我怎樣才能做到這一點?

目前我使用REGEXP,只是選擇什麼,我想是這樣的:

SELECT * FROM posts WHERE keywords REGEXP 'php|html'; 

看到了嗎?我甚至不使用1 join。現在我的數據集已經長大了,我的查詢需要一段時間才能執行。我想我必須使用像join這樣的關係特性。不過,我不確定它會比我目前的查詢更好。

無論如何,有誰知道,我怎麼能更快地得到預期的結果?

+1

你應該正常化你的數據(關鍵字內容)在適當的相關表 – scaisEdge

+0

在posts表中應該有標籤ID列,然後你可以從帖子表中選擇。 – OsamaKhalid

+0

@scaisEdge你的意思是?如果你寫了一個答案並解釋你建議的數據庫設計,那麼我會很滿意。 –

回答

1

正則表達式的處理可能很慢。使用LIKE可能會提供更好的響應時間:

SELECT * 
FROM posts 
WHERE (keywords LIKE '%php%' OR keywords LIKE '%html%') 

基於標準化的表的查詢是:

SELECT  posts.id, posts.title, posts.body, posts.keywords 
FROM  posts 
INNER JOIN pivot ON pivot.post_id = posts.id 
INNER JOIN tags ON tags.id = pivot.tag_id 
WHERE  tags.name IN ('html', 'php') 
GROUP BY posts.id 

因爲你必須確保id字段聲明作爲主鍵最佳速度,並你有索引:

tags(name) 
pivot(tag_id) 

但是,這將不會比你目前的解決方案更快,如果所有的重要部分帖子滿足條件:它可能會更慢。但是,如果例如少於1%的帖子滿足條件,那麼這可能會更好,因爲原則上執行計劃不需要包括對整個帖子表的掃描。

+0

你能告訴我你的第二個查詢中有哪些GROUP BY?對我來說似乎沒用。如果我刪除它,會發生什麼?注意到我在實際中使用了'='而不是'IN'。 –

+1

'group by'用於避免結果集中同一篇文章的重複。當一個帖子在數據透視表中有兩個匹配的條目時(一個用於「html」和一個用於「php」),就會發生這種情況。當你不使用'in'時,只用'='比較一個值,當然不需要分組。但你在問題中的例子提到了兩個標籤。 – trincot

1

您已經有了一個具有多對多關係的規範化設計。在posts表中不需要關鍵字列,因爲數據透視表已經建立了相同的關鍵字列。

你只需要正確地進行連接。試試這個:

SELECT posts.id 
    FROM posts 
LEFT OUTER JOIN pivot 
    ON posts.id = pivot.post_id 
LEFT OUTER JOIN tags 
    ON pivot.tag_id = tags.id 
WHERE tags.name = "php" or tags.name = "html" 
GROUP BY posts.id; 

這會給你帶標籤的帖子的所有id。

+0

謝謝.. upvote –

相關問題