要拆分sql列数据如下

时间:2018-10-03 07:18:04

标签: sql sql-server tsql

我有一列coordinate,其中包含许多逗号分隔的坐标。 现在我要分割这个座标。

例如:如果我有

之类的坐标
20.45847832-73.99704207,20.45868114-73.99712939,20.45849913-73.99750285,20.45831804-73.99736981,20.45848571-73.99702964,20.45851507-73.99715704,20.45852753-73.99720817,20.45849614-73.99728646,

那我只想要第一个坐标

log:20.45847832 lat:73.99704207

5 个答案:

答案 0 :(得分:1)

如果使用SQL Server 2016及更高版本,则可以使用STRING_SPLIT函数。如果我理解正确,则只想获取给定坐标中的第一个坐标。这个想法是用“,”分割,然后用“-”子串。之后,您可以根据需要选择记录。希望这能回答您的问题。

DECLARE @var VARCHAR(MAX) = '20.45847832-73.99704207,20.45868114-73.99712939,20.45849913-73.99750285,20.45831804-73.99736981,20.45848571-73.99702964,20.45851507-73.99715704,20.45852753-73.99720817,20.45849614-73.99728646,'

SELECT TOP 1 'Log:' + ColumnLog + ' Lat:' + ColumnLat AS Coordinate
FROM (
    SELECT
        SUBSTRING(VALUE, 1, CHARINDEX('-', VALUE)-1) AS ColumnLog,
        SUBSTRING(VALUE, CHARINDEX('-', VALUE) + 1, CHARINDEX('-', VALUE)-1) AS ColumnLat
    FROM STRING_SPLIT(@var, ',') WHERE RTRIM(VALUE) <> ''
) X

答案 1 :(得分:0)

提示:请勿将此类值存储在CSV列表中。这打破了1.NF,这是一个非常糟糕的设计。使用此代码修复设计并将这些坐标存储在相关的边表中。尝试使用SQL-Server-2008中引入的GEOGRAPHY abilites

您可以通过一次操作获得此信息:

DECLARE @YourString VARCHAR(1000)='20.45847832-73.99704207,20.45868114-73.99712939,20.45849913-73.99750285,20.45831804-73.99736981,20.45848571-73.99702964,20.45851507-73.99715704,20.45852753-73.99720817,20.45849614-73.99728646,';

WITH Casted(AsXml) AS
(
    SELECT CAST('<x><y>' + REPLACE(REPLACE(@YourString,',','</y></x><x><y>'),'-','</y><y>') + '</y></x>' AS XML)
          .query('/x[y/text()]')
)
SELECT * FROM Casted;

结果

<x>
  <y>20.45847832</y>
  <y>73.99704207</y>
</x>
<x>
  <y>20.45868114</y>
  <y>73.99712939</y>
</x>
<x>
  <y>20.45849913</y>
  <y>73.99750285</y>
</x>
<x>
  <y>20.45831804</y>
  <y>73.99736981</y>
</x>
<x>
  <y>20.45848571</y>
  <y>73.99702964</y>
</x>
<x>
  <y>20.45851507</y>
  <y>73.99715704</y>
</x>
<x>
  <y>20.45852753</y>
  <y>73.99720817</y>
</x>
<x>
  <y>20.45849614</y>
  <y>73.99728646</y>
</x>

XQuery/Xpath中使用它,如下所示:

WITH Casted AS
(
    SELECT CAST('<x><y>' + REPLACE(REPLACE(@YourString,',','</y></x><x><y>'),'-','</y><y>') + '</y></x>' AS XML)
          .query('/x[y/text()]') AS AsXml
)
SELECT x.value('y[1]/text()[1]','decimal(12,8)') AS [log]
      ,x.value('y[2]/text()[1]','decimal(12,8)') AS [lat]
FROM Casted
CROSS APPLY AsXml.nodes('/x') A(x);

您会得到

log         lat
20.45847832 73.99704207
20.45868114 73.99712939
20.45849913 73.99750285
20.45831804 73.99736981
20.45848571 73.99702964
20.45851507 73.99715704
20.45852753 73.99720817
20.45849614 73.99728646

答案 2 :(得分:0)

我将其添加为新答案,因为它采用了完全不同的方法:使用SQL-Server-2016 +,您可以使用JSON功能:

DECLARE @YourString VARCHAR(1000)='20.45847832-73.99704207,20.45868114-73.99712939,20.45849913-73.99750285,20.45831804-73.99736981,20.45848571-73.99702964,20.45851507-73.99715704,20.45852753-73.99720817,20.45849614-73.99728646,';

SELECT *
FROM OPENJSON('[{"lon":"' + REPLACE(REPLACE(@YourString,',','"},{"lon":"'),'-','","lat":"') + '"}]')
WITH(lon float '$.lon'
    ,lat float '$.lat');

结果

lon         lat
20,45847832 73,99704207
20,45868114 73,99712939
20,45849913 73,99750285
20,45831804 73,99736981
20,45848571 73,99702964
20,45851507 73,99715704
20,45852753 73,99720817
20,45849614 73,99728646
0           NULL

答案 3 :(得分:0)

很抱歉添加第三个答案,但这又是一种全新的方法。

如果您需要问题所陈述格式的第一对坐标,那么这是一个真正的在线用户:

DECLARE @YourString VARCHAR(1000)='20.45847832-73.99704207,20.45868114-73.99712939,20.45849913-73.99750285,20.45831804-73.99736981,20.45848571-73.99702964,20.45851507-73.99715704,20.45852753-73.99720817,20.45849614-73.99728646,';

SELECT 'log:' + STUFF(LEFT(@YourString,PATINDEX('%,%',@YourString)-1),PATINDEX('%-%',@YourString),1,' lat:');

结果

log:20.45847832 lat:73.99704207

根据您的评论更新

尝试一下

DECLARE @mockupTable TABLE(tagdata VARCHAR(1000));
INSERT INTO @mockupTable VALUES('20.45847832-73.99704207,20.45868114-73.99712939,20.45849913-73.99750285,20.45831804-73.99736981,20.45848571-73.99702964,20.45851507-73.99715704,20.45852753-73.99720817,20.45849614-73.99728646,');

SELECT FirstPair
      ,LEFT(FirstPair,PATINDEX('%-%',FirstPair)-1) AS lon
      ,SUBSTRING(FirstPair,PATINDEX('%-%',FirstPair)+1,1000) AS lat
FROM @mockupTable t
CROSS APPLY(SELECT LEFT(tagdata,PATINDEX('%,%',tagdata)-1)) A(FirstPair);

答案 4 :(得分:0)

SQL Server支持spatial data。您可以将此字符串视为MULTIPOINT,对其进行解析并返回其中的第一点,例如:

declare @string nvarchar(200)='20.45847832-73.99704207,20.45868114-73.99712939,20.45849913-73.99750285,20.45831804-73.99736981,20.45848571-73.99702964,20.45851507-73.99715704,20.45852753-73.99720817,20.45849614-73.99728646'

declare @point geography=geography::Parse('MULTIPOINT (' + replace(@string,'-', ' ') +')')
                                   .STPointN(1)

select @point.Lat,@point.Long

'MULTIPOINT (' + replace(@string,'-', ' ') +')'用空格替换-并创建一个可解析为multipoint的字符串:

MULTIPOINT (20.45847832 73.99704207,20.45868114 73.99712939,20.45849913 73.99750285,20.45831804 73.99736981,20.45848571 73.99702964,20.45851507 73.99715704,20.45852753 73.99720817,20.45849614 73.99728646)

geography::Parse可以解析空间特征的熟知文本表示​​形式,并将特征本身作为geography对象返回。

之后。 STPointN(1)返回多点中的第一个点。可以通过纬度和经度属性获得坐标

ADO.NET通过Microsoft.Sql.Types库支持空间类型。 geography个对象作为SqlGeography个实例返回