如何使用COUNT()来解析nvarchar字段中的单个单词?

时间:2013-08-29 20:16:05

标签: sql-server tsql

所以我的查询:

SELECT Tags, COUNT(Tags) AS Listings
FROM Job
WHERE datepart(year, dateposted)=2013
GROUP BY Tags
ORDER BY Listings DESC

输出:

+----------------------+----------+
|         Tags         | Listings |
+----------------------+----------+
| java c++             |       41 |
| software development |       41 |
| java c++ c#          |       31 |
|                      |       25 |
| sysadmin             |       25 |
| see jd               |       24 |
| java c++ ood         |       23 |
| java                 |       23 |
+----------------------+----------+

我希望它像这样出来:

+----------------------+----------+
|         Tags         | Listings |
+----------------------+----------+
| java                 |       118|
| c++                  |       95 |
| ood                  |       23 |
| see                  |       24 |
| jd                   |       24 |
| software development |       41 |
| sysadmin             |       25 |
| c#                   |       31 |
+----------------------+----------+

如何计算字段中的每个单词而不是整个字段?标签列是nvarchar。

3 个答案:

答案 0 :(得分:8)

首先,你的表结构很糟糕。将数据存储在这样的列表中会让您感到头疼,类似于您现在尝试做的事情。

分割功能的问题是你不知道software development或其他多字标签是什么 - 是一个字还是一个字?

我认为解决此问题的唯一方法是使用您的代码创建一个表或使用类似于以下内容的派生表:

;with cte (tag) as
(
  select 'java' union all
  select 'c++' union all
  select 'software development' union all
  select 'sysadmin' union all
  select 'ood' union all
  select 'jd' union all
  select 'see' union all
  select 'c#'
)
select c.tag, count(j.tags) listings
from cte c
inner join job j
  on j.tags like '%'+c.tag+'%'
group by c.tag

SQL Fiddle with Demo。使用它你可以得到一个结果:

|                  TAG | LISTINGS |
|                 java |        9 |
|                  c++ |       10 |
| software development |        4 |
|             sysadmin |        2 |
|                  ood |        6 |
|                   jd |        3 |
|                  see |        2 |
|                   c# |        1 |

评论中指出的上述问题是如何确定您是否有softwaredevelopment标记,这些标记将与上述查询匹配。

您遇到此问题的最佳解决方案是将标记存储在类似于以下内容的单独表中:

create table tags
(
  tag_id int,
  tag_name varchar(50)
);

然后,您可以使用JOIN表将作业连接到标记:

create table tag_job
(
  job_id int,
  tag_id int
);

一旦你有类似的设置,那么查询你的数据会变得容易得多:

select t.tag_name,
  count(tj.tag_id) listings
from tags t
inner join tag_job tj
  on t.tag_id = tj.tag_id
group by t.tag_name

See demo

答案 1 :(得分:0)

您可能需要拆分单词。

这是SQL Server中分割器的一个很好的系列: SqlServerCentral.com

我不知道你将如何区分软件开发"但作为单个标签。如果您在其他地方有可接受的标签列表,则可以使用它来执行计数。

如果您有可用标记列表,这里有一种方法不需要拆分。

Sql Fiddle Example

如果您的标记包含在另一个标记中,则此方法可能存在问题。即'软件'和'软件开发'

答案 2 :(得分:0)

这就是我解决问题的方法。

SELECT TOP 50 Tags.s Tag, COUNT(Tags.s) AS Listings
FROM Job
CROSS APPLY [dbo].[SplitString](Tags,' ') Tags
WHERE NOT Job.Tags IS NULL and datepart(year,job.datecreated) = 2013
GROUP BY Tags.s
ORDER BY Listings DESC