我的表中有以下数据:
URL TIME DATE
--------------------------------------
/x 11 2013-08-01
/x 11 2013-08-01
/pl/ 11 2013-08-01
/pl/ 11 2013-08-03
/pl/XXX/ 11 2013-08-01
/pl/XXX/ 11 2013-08-04
/pl/XXX/1 11 2013-08-01
/pl/XXX/2 11 2013-08-01
/pl/YYY/ 11 2013-08-01
/pl/YYY/1 11 2013-08-01
/pl/YYY/2 11 2013-08-04
/pl/YYY/3 11 2013-08-04
有没有办法按URL分组到SQL Server中的第三个斜杠(/
)?不幸的是,存在少于三个的记录。
答案 0 :(得分:9)
计算字符串中斜杠数的一个技巧是:
len(url) - len(replace(url,'/',''))
然后,您可以使用charindex
三次查找第三个斜杠的位置:
select BeforeThirdSlash
, max([date])
from (
select case
when len(url) - len(replace(url,'/','')) < 3 then url
else substring(url, 1, charindex('/', url, charindex('/',
url, charindex('/', url)+1)+1)-1)
end as BeforeThirdSlash
, *
from @t
) as SubQueryAlias
group by
BeforeThirdSlash
答案 1 :(得分:3)
一个简单的表达式,可以让你获取第三个'/'
字符的子字符串如下:
case
when patindex('%/%/%/%', url) = 0 then url
else left(url,charindex('/',url,charindex('/',url,charindex('/',url)+1)+1))
end
patindex
检查至少有三个斜杠; left
提取子字符串,包括第三个子字符串。
有了这个表达式,写group by
很简单:
SELECT
url3, max(tm), max(dt)
FROM (
SELECT
CASE
WHEN patindex('%/%/%/%', url) = 0 THEN url
ELSE left(url,charindex('/',url,charindex('/',url,charindex('/',url)+1)+1))
END AS url3
, tm
, dt
FROM test
) x
GROUP BY url3
答案 2 :(得分:2)
您可以找到/
的每个位置的位置并修剪到MAX(position)
- 假设第三个/
是根据数据的最后一个/
。
DECLARE @tbl TABLE ( u VARCHAR(255), t INT, d DATE)
INSERT INTO @tbl (u, t, d) VALUES
('/x', 11, '2013-08-01'),
('/x', 11, '2013-08-01'),
('/pl/', 11, '2013-08-01'),
('/pl/', 11, '2013-08-03'),
('/pl/XXX/', 11, '2013-08-01'),
('/pl/XXX/', 11, '2013-08-04'),
('/pl/XXX/1', 11, '2013-08-01'),
('/pl/XXX/2', 11, '2013-08-01'),
('/pl/YYY/', 11, '2013-08-01'),
('/pl/YYY/1', 11, '2013-08-01'),
('/pl/YYY/2', 11, '2013-08-04'),
('/pl/YYY/3', 11, '2013-08-04')
;WITH split AS (
SELECT u, 1 s, CHARINDEX('/', u) p
FROM @tbl
UNION ALL
SELECT u, p + 1, CHARINDEX('/', u, p + 1)
FROM split
)
SELECT LEFT(t.u, split.i), MAX(t.t), MAX(t.d)
FROM @tbl t
JOIN (
SELECT u, MAX(p) i
FROM split
GROUP BY u
) split ON split.u = t.u
GROUP BY LEFT(t.u, split.i)
稍微调整一下cte即可控制出现次数
DECLARE @n INT = 3 -- 'nth occurence'
;WITH split AS (
SELECT u, CHARINDEX('/', u) i, 1 r
FROM (
SELECT DISTINCT u
FROM @tbl
) t
WHERE CHARINDEX('/', u) > 0
UNION ALL
SELECT u, CHARINDEX('/', u, i + 1), r + 1
FROM split
WHERE r < @n
AND CHARINDEX('/', u, i + 1) > 0
)
SELECT LEFT(t.u, split.i) u, MAX(t.t) t , MAX(t.d) d
FROM @tbl t
JOIN split ON split.u = t.u
GROUP BY LEFT(t.u, split.i)