sql查询从单个表中获取标记信息

时间:2011-03-07 11:25:40

标签: mysql sql

我有一个表(Mysql),其中包含带有coloumns中标签的不同片段

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

我想做一个select语句,这样我就可以在我的网站上构建标签云。

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

记住,tages并不总是按空间分配,有些tages用逗号分隔(,)

然后我需要一个查询来获取具有特定tages的所有记录。我认为我可以使用类似的东西,直到有更好的解决方案。

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

请寻找优化的解决方案。

3 个答案:

答案 0 :(得分: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)-@delimiterIndex)
            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

填充触发器并填充新表,使您更容易,而不会影响现有代码。当然,你需要用一个替换所有已知的分界符才能工作。
添加或修改的任何新记录都会自动触发触发器。

答案 1 :(得分: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%'

答案 2 :(得分:0)

首先,你必须用'#'等固定的“分隔符”字符替换所有字符,如','space等。你可以使用临时表。

然后你必须创建一个循环遍历字段并搜索和计算单个标记的函数。