我有一个像这样的结构的表
ID pointCount pointSeries
1 282 35.1079,-111.0151,35.1088,-111.0196...
显然点数系列是字符串有一对lat lon作为点。我想选择pointSeries到一个新表
ID Lat Lon
1 35.1079 -111.0151
1 35.1088 -111.0196
我可以做分割并选择查询的最佳方式是什么?
答案 0 :(得分:4)
您需要具有将逗号分隔的字符串拆分为单独行的函数。以下是Jeff Moden的DelimitedSplit8K函数。
CREATE FUNCTION [dbo].[DelimitedSplit8K](
@pString NVARCHAR(4000), @pDelimiter NCHAR(1)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,E2(N) AS (SELECT 1 FROM E1 a, E1 b)
,E4(N) AS (SELECT 1 FROM E2 a, E2 b)
,cteTally(N) AS(
SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
,cteStart(N1) AS(
SELECT 1 UNION ALL
SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
),
cteLen(N1,L1) AS(
SELECT
s.N1,
ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
FROM cteStart s
)
SELECT
ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
Item = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l
然后您需要旋转分割的结果以获得所需的结果:
;WITH CteSplitted AS(
SELECT
t.ID,
x.ItemNumber,
Item = CAST(x.Item AS NUMERIC(16,4)),
RN = (ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ItemNumber) + 1) / 2
FROM Test t
CROSS APPLY dbo.DelimitedSplit8K(t.PointSeries, ',') x
)
SELECT
ID,
Lat = MAX(CASE WHEN ItemNumber % 2 = 1 THEN Item END),
Lon = MAX(CASE WHEN ItemNumber % 2 = 0 THEN Item END)
FROM CteSplitted
GROUP BY ID, RN