IMO,設計方法是什麼讓這很難。僅僅因爲您允許用戶分配標籤並不意味着標籤必須作爲單個分隔的單詞列表存儲。您可以標準化結構成類似:
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
)
你需要使用字符串操作每個森泰斯轉換爲一組單詞。如果你創建一個表值函數,它接受一個字符串並輸出一個字表,然後你可以使用'myData CROSS APPLY myFunction(myTable.sentance)',然後使用GROUP BY來計算一切。確切地說需要什麼規則來打破一個單獨的單詞,我會留給你或其他:) – MatBailie