计算单个帖子数据浏览器中的标签数量

Posted

技术标签:

【中文标题】计算单个帖子数据浏览器中的标签数量【英文标题】:Counting the number of tags in a single post - data explorer 【发布时间】:2019-05-26 20:59:04 【问题描述】:

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

Other posts 建议创建一个函数来拆分标签,但是你不能创建数据交换的函数。

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

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

【问题讨论】:

请显示表格的结构。 还有一些示例数据和预期输出。 我认为标签存储为例如(您的问题):[<sql><sql-server><tsql><split><dataexplorer>] 所以您可以通过LEN(Tage) - LEN(REPLACE(< or > FROM Tag)) 获取标签计数 mel,如果我理解正确,Posts.Tags 列是一个带有标签列表的字符串。如果是这样,您将不得不将其拆分为单个令牌并使用它们加入您的Tags 表(而不是p.Id)。但这是疯狂的猜测...尝试使用 DDL、示例数据和加速输出设置 minimal reproducible example。 @Shnugo 他们在这里使用架构data.stackexchange.com/***/query/new 【参考方案1】:

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

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

SEDE Demo

【讨论】:

这很好,谢谢!你怎么知道标签是用' @mel SELECT TagName FROM Tags WHERE TagName LIKE '%&lt;%' OR TagName LIKE '%&gt;%' -- 0 行【参考方案2】:

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

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

如果标签可能包含禁止字符(如&amp;, &lt; and &gt; 等等),您可以使用额外的内部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);

更新:更简单的方法

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

这个查询将返回一个空元素列表as xml,只需将结束的&gt; 替换为/&gt;。然后查询将使用/* 迭代所有这些并通过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:我刚试过这个here

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

【讨论】:

感谢详细的解决方案!更新 2 中的链接将我路由到一个新查询,而不是您编写的那个。请在修复后通知我,以便我查看您的操作! @mel,只需将我的查询复制到那里并使用Posts 而不是@mockupPosts【参考方案3】:

我猜你需要这样的东西

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

【讨论】:

那是完全错误的。因为我们有 3 个表(帖子、帖子标签、标签)。这里是多对多的关系。 你在哪里说的?【参考方案4】:

您可以使用 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 Demo

更新:

这也是另一种方式

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 Demo

【讨论】:

以上是关于计算单个帖子数据浏览器中的标签数量的主要内容,如果未能解决你的问题,请参考以下文章

判断帖子中图片数量

在数据浏览器中查询增长最快的标签?

如何通过某些标签获取帖子和评论的用户数?

计算 Meteor 中帖子中的评论数

您如何按包含标签的帖子数量对博客帖子标签列表进行排序(在 Eleventy 中使用 Nunjucks)?

类别集合的最佳设计