2011-03-07 48 views
1

標籤信息我有一個表(MySQL的)與標籤不同片段在coloumnsSQL查詢來從單個表

table snippets 
--------------- 
Id title source tag 
1 "title" "srouce code" "Zend, Smarty" 
2 "title2" "srouce code2" "Zend jquery" 
3 "title3" "srouce code3" "doctrine" 

我想要做一個選擇語句,這樣我就可以建立一個標籤雲我的網站。

Zend(2), smarty(1), jquery(1), doctrine(1) 

記住每日新聞並不總是受到空間sperated,一些產品關鍵詞之間用逗號(,)隔開

然後我需要一個查詢具體產品關鍵詞獲取的所有記錄。我認爲我可以使用類似的東西,直到有更好的解決方案。

Select * from snippets where tag like "%ZEND%" 

請尋求優化的解決方案。

+0

當標記爲負時做任何一條評論....這個問題有什麼問題嗎? – Developer 2011-03-07 11:35:26

回答

1

創建三張表!

table snippets 
id | title | source_code 
1 "title" "srouce code" 
2 "title2" "srouce code2" 
3 "title3" "srouce code3" 

table tags 
id | tag 
1 "zend" 
2 "smarty" 
3 "doctrine" 
4 "jquery" 

table snippets_tags 
id | snippet_id | tag_id 
1  1   1 
2  1   2 
3  2   1 
4  2   4 
5  3   3 

提示:小寫的標籤,因爲「Zend公司」和「Zend的」相同

現在你的標籤雲查詢應該像

SELECT tags.name, COUNT(snippets_tags.id) AS snippet_count 
    FROM tags LEFT JOIN snippets_tags ON snippets_tags.tag_id = tags.id 
     GROUP BY tags.id 

給你一個結果像

name | snippet_count 
zend   2 
smarty  1 
doctrine  1 
jquery  1 

要選擇屬於某個標記的所有代碼段:

SELECT snippets.* FROM snippets, tags, snippets_tags 
    WHERE 
    snippets_tags.snippets_id = snippet.id AND 
    snippets_tags.tag_id = tags.id AND 
    tags.name LIKE '%zend%' 
+0

,這是很正常化。有沒有辦法在SQL中,我可以與現有的表結構,因爲每一件事情已經做得很糟糕。不想花太多時間來改變整個結構。是否有任何SQL查詢可以完成現有結構的工作。感謝您的幫助雪橇。我真的很有趣。 – Developer 2011-03-07 12:14:02

+0

如果性能無關緊要,您可以使用正則表達式: 'SELECT * FROM tags WHERE name REGEXP「(^ | [,] +)zend($ | [,] +)」'只讓您獲得「zend」標籤像「zendalicous」不匹配!但是「blabla,zend,something」或者「blabla zend,blabla」會匹配。 [詳細瞭解模式匹配](http://dev.mysql.com/doc/refman/5.0/en/pattern-matching.html) – sled 2011-03-07 12:24:49

0

首先,您必須用'#'等固定的「分隔符」字符替換'''空格等所有字符。你可以使用臨時表。

然後,您必須創建一個循環遍歷字段並搜索和計數單個標籤的函數。

+0

是否有任何的SQL解決方案?我知道這不是存儲在單個表格中的最佳方式。但這正是預定員所做的。所以我必須解決這個問題。 – Developer 2011-03-07 11:41:48

1

你有沒有想過將源代碼和標籤分離到不同的表中?

Source Table 
ID, Title, Source 
1 "t1" "sc" 
2 "t2" "sc" 
3 "t3" "sc" 

Tag Table 
ID, Tag 
1 "Zend" 
2 "Smarty" 
3 "jquery" 
4 "doctrine" 

SourceTagLink Table 
SourceID, TagID 
1   1 
1   2 
2   1 
2   3 
3   4 

你有,你可以選擇,或添加標籤唯一列表的方式。 你不會做任何字符串解析,所以你的選擇會更快。與您在本網站上爲您的帖子分配標籤的方式類似。

編輯
這是我用一個多值的字符串轉換成表格與它寫一個列的函數MSSQL,但你應該能夠將其轉換到MySQL

CREATE FUNCTION [dbo].[ParseString](@String NVARCHAR(4000), @Delimiter CHAR(1)=',') 
      RETURNS @Result TABLE(tokens NVARCHAR(4000)) 
    AS 
    BEGIN 
     -- We will be seearching for the index of each occurrence of the given 
     -- delimiter in the string provided, and will be extracting the characters 
     -- between them as tokens. 
     DECLARE @delimiterIndex INT 
     DECLARE @token NVARCHAR(4000) 

     -- Try to find the first delimiter, and continue until no more can be found. 
     SET @delimiterIndex = CHARINDEX(@Delimiter, @String) 
     WHILE (@delimiterIndex > 0) 
     BEGIN 
      -- We have found a delimiter, so extract the text to the left of it 
      -- as a token, and insert it into the resulting table. 
      SET @token = LEFT(@String, @delimiterIndex-1) 
      INSERT INTO @Result(tokens) VALUES (LTRIM(RTRIM(@token))) 

      -- Chop the extracted token and this delimiter from our search string, 
      -- and look for the next delimiter. 
      SET @String = RIGHT(@String, LEN(@String)[email protected]) 
      SET @delimiterIndex = CHARINDEX(@Delimiter, @String) 
     END 
     -- We have no more delimiters, so place the remainder of the string 
     -- into the result as our last token. 
     SET @token = @String 
     INSERT INTO @Result(tokens) VALUES (LTRIM(RTRIM(@token))) 
     RETURN 
    END 

基本上你怎麼稱呼它像

ParseString('this be a test', ' ') 
it will return a single column table 

this  
be 
a 
test 

ParseString('this:be a test', ':') 
returns 

this 
be a test 

你可以在更新觸發器添加一個調用該函數來填充新表,以幫助您做出選擇更加容易。一旦觸發建成,只是做類似下面

Update yourTable 
Set Title = Title 

,填補火扳機和填充新表,讓你的一切更容易在不影響現有代碼的簡單更新。當然,你需要用一個單一的替換所有已知的定界符來使其工作。
添加或修改的任何新記錄都會自動激發觸發器。

+0

這可能是標準化表格的最佳方法。但我不想改變表格的結構,因爲它可能會使其他模塊不穩定。這是唯一的方法嗎?或者我可以解決一些SQL查詢。 – Developer 2011-03-07 11:48:57

+0

請參閱編輯回答 – 2011-03-07 12:13:43