如何分组字符串部分?

时间:2015-03-16 14:21:50

标签: sql sql-server-2008 sql-server-2008-r2 aggregate-functions

我有一个包含来自门户网站的日志的表,它包含访问过的网址,请求持续时间,参考资料...

其中一列是路径信息,其中包含以下字符串:

/admin/
/export/
/project2/
/project1/news
/project1/users
/user/id/1
/user/id/1/history
/user/id/2
/forum/topic/14/post/456

我想用sql查询根据此列计算一些统计数据,所以我想知道如何根据路径信息的第一部分创建聚合

让我计算以/admin//export//project1//project2//user//forum/开头的网址数量, ...

使用正则表达式使用编程语言很容易,但我读到SQLServer上不存在类似的函数。

2 个答案:

答案 0 :(得分:2)

我会使用CHARINDEX()来查找在前导的第一个字符'/'之后开始的第一次出现的“/”,所以在第二个字符之后的任何内容都会被删除。

  select
          LEFT( pathInfo, CHARINDEX( '/', pathInfo, 2 )) as RootLevelPath,
          count(*) as Hits
       from
          temp
       group by
          LEFT( pathInfo, CHARINDEX( '/', pathInfo, 2 ))

Working result from SQLFiddle

答案 1 :(得分:0)

DRapp非常适合对URL的第一个片段进行分组。如果需要按其他级别进行分组,则可能难以管理嵌套的LEFT / CHARINDEX语句。

以下是按参数化级别分组的一种方法:

declare @t table (pathId int identity(1,1) primary key, somePath varchar(100));
insert into @t
    select '/admin/' union all
    select '/export/' union all
    select '/project2/' union all
    select '/project1/news' union all
    select '/project1/users' union all
    select '/user/id/1' union all
    select '/user/id/1/history' union all
    select '/user/id/2' union all
    select '/forum/topic/14/post/456' union all
    select '/forum/topic/14/post/789' union all
    select '/forum/topic/14/post/789'


declare @level int =1;

;with fragments as
(   select  pathId,
            [n] = x.query('.'),
            [Fragment] = x.value('.', 'varchar(100)')
    from    (   select  PathId, 
                        cast('<r>' + replace(stuff(somePath, 1, 1, ''), '/', '</r><r>') + '</r>' as xml)
                            .query('r[position()<=sql:variable("@level")]')
                from @t
            ) d (PathId, X)
)
select  count(*), [path] = max(r.v)
from    fragments f
cross
apply   (   select  '/' + p.n.value('.', 'varchar(100)')
            from    fragments
            cross
            apply   n.nodes('r')p(n)
            where   PathId = f.PathId
            for xml path('')
        ) r(v)
group
by      fragment;