1

我正在尝试编写一个查询来计算单个帖子下的标签数量。我不知何故无法将标签分成一行并计算这些标签。

其他帖子建议创建一个函数来拆分标签,但您不能在数据交换上创建函数。

这是我到目前为止的查询,它只会给我帖子和标签中的帖子。

SELECT p.Id, p.Title, p.Tags, t.TagName
FROM Posts as p 
INNER JOIN Tags as t ON p.Id = t.Id
4

4 回答 4

2

Tags您可以使用列计算标签数量:

SELECT Id, Title, Tags, LEN(Tags) - LEN(REPLACE(Tags, '<','')) AS tag_number
FROM Posts as p 
WHERE Id = 2647

SEDE 演示

于 2018-12-29T10:51:55.820 回答
1

这很接近猜测,但我的魔法水晶球(和马丁史密斯)告诉我,你可能正在寻找这样的东西:

DECLARE @mokupPosts TABLE(ID INT IDENTITY, SomePost VARCHAR(250),Tags VARCHAR(250));
INSERT INTO @mokupPosts VALUES
 ('First post','<matlab><plot><ternary><ternplot>')
,('Second post','<powershell><java><python>')
,('Third post','<image><opencv><image-processing>');

--查询将Post分别返回每个标记的多行。

SELECT p.*
      ,B.token.value('text()[1]','varchar(100)') Token
FROM @mokupPosts p
CROSS APPLY(SELECT CAST('<x>' + REPLACE(REPLACE(REPLACE(REPLACE(p.Tags,'><','||'),'<',''),'>',''),'||','</x><x>') + '</x>' AS XML)) A(Casted)
CROSS APPLY A.Casted.nodes('/x') B(token);

您可以轻松地INNER JOIN将此令牌直接添加到您现有的表Tags上并执行分组COUNT()

如果标签可能包含禁止字符(比如&, < and >和更多),您可以使用额外的内部SELECT FOR XML PATH('')来隐式转义它们:

SELECT p.*
      ,B.token.value('text()[1]','varchar(100)') Token
FROM @mokupPosts p
CROSS APPLY(SELECT CAST('<x>' + REPLACE((SELECT REPLACE(REPLACE(REPLACE(p.Tags,'><','||'),'<',''),'>','') AS [*] FOR XML PATH('')),'||','</x><x>') + '</x>' AS XML)) A(Casted)
CROSS APPLY A.Casted.nodes('/x') B(token);

更新:更简单的方法

注意:标签不得包含元素名称中禁止使用的字符,例如&, < and >(以及更多)!

此查询将返回一个空元素列表作为 xml,只需将结尾替换>/>. 然后查询将用于/*迭代所有这些并通过以下方式返回它们的名称local-name(.)

SELECT p.*
      ,B.token.value('local-name(.)','varchar(100)')AS Token
FROM @mokupPosts p
CROSS APPLY(SELECT CAST(REPLACE(p.Tags,'>','/>') AS XML)) A(Casted)
CROSS APPLY A.Casted.nodes('/*') B(token)

结果和上面一样。。。

更新2:我刚刚在这里尝试过

...它的工作原理:-)

于 2018-12-29T16:51:17.523 回答
0

您可以使用 JOIN 将其作为

SELECT P.ID,
       P.Title,
       P.Tags,
       COUNT(Tags) TagsCount
FROM Posts P INNER JOIN PostTags PT
       ON P.Id = PT.PostId
WHERE P.ID = 53243136
GROUP BY P.ID,
         P.Title,
         P.Tags;

SEDE 演示

更新:

这里也是另一种方式

SELECT P.ID,
       P.Title,
       P.Tags,
       COUNT(TT.Value) - 1 TagsCount
       FROM Posts P CROSS APPLY (SELECT Value FROM STRING_SPLIT(Tags, '>')) TT
WHERE P.ID = 53243136
GROUP BY P.ID,
         P.Title,
         P.Tags; 

SEDE 演示

于 2018-12-29T11:47:55.707 回答
0

我猜你需要这样的东西

SELECT p.Id, p.Title, p.Tags, count(t.TagName)
FROM Posts as p 
INNER JOIN Tags as t ON p.Id = t.Id
group by p.Id, p.Title, p.Tags
于 2018-12-29T10:50:41.077 回答