拆分字符串并选择新表

时间:2015-03-06 02:10:37

标签: sql sql-server tsql

我有一个像这样的结构的表

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

我可以做分割并选择查询的最佳方式是什么?

1 个答案:

答案 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