2011-10-06 5 views
1

Juste une question exploratoire pour voir si quelqu'un a fait cela ou si, en fait c'est possible. Nous savons tous ce qu'est un nuage d'étiquettes, et généralement, un nuage d'étiquettes est créé par quelqu'un qui attribue des étiquettes. Est-il possible, dans les fonctionnalités actuelles de SQL Server de créer cela automatiquement, peut-être via le déclencheur quand une table a un enregistrement ajouté ou mis à jour, en regardant les données dans une certaine colonne et obtenir des mots populaires? Il est similaire à cette question: How can I get the most popular words in a table via mysql?. Mais, c'est MySQL pas MSSQL.TSQL - Interrogation d'une colonne de table pour extraire des mots populaires pour un nuage de tags

Merci d'avance. James

+1

Vous auriez besoin d'utiliser la manipulation de chaînes pour convertir chaque Sentance à un ensemble de mots. Si vous créez une fonction de valeur de table qui accepte une chaîne et affiche une table de mots, vous pouvez utiliser 'myData CROSS APPLY myFunction (myTable.sentance)', puis utiliser un GROUP BY pour tout compter. Exactement ce que les règles seraient nécessaires pour casser une phrase en mots individuels, je vais laisser à vous ou à d'autres :) – MatBailie

Répondre

6

Voici une bonne partie sur l'analyse syntaxique chaîne délimitée en lignes:
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: Opposite to string concatenation - how to split string into multiple records

Si vous voulez analyser tous les mots, vous pouvez utilisez l'espace '' comme délimiteur, alors vous obtenez une ligne pour chaque mot.

suivant vous suffit de sélectionner le jeu de résultats GROUP par le mot ing et l'agrégation des COUNT

DEMANDER résultats et vous y êtes.

+0

Exactement ce dont j'avais besoin, merci. Que regardons-nous en ce qui a trait à la performance? – jamesmhaley

+0

performances @sparkyfied sera assez mauvaise. Si vous avez plusieurs lignes et que vous en analysez chacune dans une table temporaire, votre curseur peut prendre un certain temps. Heureusement, vous n'avez pas besoin de produire un tag-cloud très souvent. – Matthew

+0

Donc, la meilleure option est sur un déclencheur lorsque l'administrateur ajoute un enregistrement ou met à jour une ligne? – jamesmhaley

1

IMO, l'approche de conception est ce qui rend cela difficile. Le simple fait que vous autorisiez les utilisateurs à attribuer des tags ne signifie pas que les tags doivent être stockés dans une liste de mots délimitée. Vous pouvez normaliser la structure en quelque chose comme:

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)) 

Maintenant, votre question devient trivial:

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 

Si vous insistez sur le stockage des balises comme valeurs délimitées, seule solution est de diviser les valeurs de leur delimiter en écrivant une fonction Split personnalisée, puis faites votre compte. En bas se trouve un exemple de fonction Split. Avec elle, votre requête ressemblerait à quelque chose comme (en utilisant un séparateur virgule):

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 

Fonction Split:

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 

) 
Questions connexes