TSQL - запрос столбца таблицы для извлечения популярных слов для облака тегов - PullRequest
1 голос
/ 06 октября 2011

Просто предварительный вопрос, чтобы выяснить, сделал ли это кто-то или вообще это возможно.

Мы все знаем, что такое облако тегов, и обычно облако тегов создается кем-то.присвоение тегов.Возможно ли в текущих функциях SQL Server создать это автоматически, возможно, с помощью триггера, когда в таблицу добавлена ​​или обновлена ​​запись, просмотрев данные в определенном столбце и получив популярные слова?

Этопохож на этот вопрос: Как я могу получить самые популярные слова в таблице с помощью MySQL? .Но это MySQL, а не MSSQL.

Заранее спасибо.Джеймс

Ответы [ 2 ]

6 голосов
/ 06 октября 2011

Вот хороший бит при разборе строки с разделителями на строки:
http://anyrest.wordpress.com/2010/08/13/converting-parsing-delimited-string-column-in-sql-to-rows/

http://www.sqlteam.com/article/parsing-csv-values-into-multiple-rows

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=50648

T-SQL: в отличие от конкатенации строк - как разбить строку на несколько записей

Если вы хотите проанализировать все слова, вы можете использовать пробел '' в качестве разделителя, затем вы получите строку для каждого слова.

Далее вы просто выбираете набор результатов GROUP, используя слово и агрегируя COUNT

Порядок ваших результатов, и вы на месте.

1 голос
/ 06 октября 2011

ИМО, подход к дизайну делает это трудным. То, что вы позволяете пользователям назначать теги, не означает, что теги должны храниться в виде единого списка слов с разделителями. Вы можете нормализовать структуру в нечто вроде:

Create Table Posts ( Id ... not null primary key )
Create Table Tags( Id ... not null primary key, Name ... not null Unique )
Create Table PostTags
    ( PostId ... not null References Posts( Id )
    , TagId ... not null References Tags( Id ) )

Теперь ваш вопрос становится тривиальным:

Select T.Id, T.Name, Count(*) As TagCount
From PostTags As PT
    Join Tags As T
        On T.Id = PT.TagId
Group By T.Id, T.Name
Order By Count(*) Desc

Если вы настаиваете на сохранении тегов как значений с разделителями, то единственным решением будет разделить значения на их разделителе, написав пользовательскую функцию Split, а затем подсчитать. Внизу приведен пример функции разделения. При этом ваш запрос будет выглядеть примерно так (с использованием запятой):

Select Tag.Value, Count(*) As TagCount
From Posts As P
    Cross Apply dbo.Split( P.Tags, ',' ) As Tag
Group By Tag.Value
Order By Count(*) Desc

Функция разделения:

Create Function [dbo].[Split]
(   
    @DelimitedList nvarchar(max)
    , @Delimiter nvarchar(2) = ','
)
RETURNS TABLE 
AS
RETURN 
    (
    With CorrectedList As
        (
        Select Case When Left(@DelimitedList, DataLength(@Delimiter)/2) <> @Delimiter Then @Delimiter Else '' End
            + @DelimitedList
            + Case When Right(@DelimitedList, DataLength(@Delimiter)/2) <> @Delimiter Then @Delimiter Else '' End
            As List
            , DataLength(@Delimiter)/2 As DelimiterLen
        )
        , Numbers As 
        (
        Select TOP (Coalesce(Len(@DelimitedList),1)) Row_Number() Over ( Order By c1.object_id ) As Value
        From sys.objects As c1
            Cross Join sys.columns As c2
        )
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
        , Substring (
                    CL.List
                    , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen     
                    , Case
                        When CharIndex(@Delimiter, CL.list, N.Value + 1)                            
                            - CharIndex(@Delimiter, CL.list, N.Value)
                            - CL.DelimiterLen < 0 Then Len(CL.List)
                        Else CharIndex(@Delimiter, CL.list, N.Value + 1)                            
                            - CharIndex(@Delimiter, CL.list, N.Value)
                            - CL.DelimiterLen
                        End
                    ) As Value
    From CorrectedList As CL
        Cross Join Numbers As N
    Where N.Value < Len(CL.List)
        And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter

)
...