SQL从值组中选择

时间:2018-10-01 08:51:06

标签: sql sql-server

我有一个包含用〜分隔的连续值组的字段。

57|0|0|2|||~56|0|0|2|||~55|0|0|2|||~54|0|0|3|4|5|~53|0|0|4|||~52|0|0|4|||~51|0|0|2|||~

每个组均以ID开头,例如5个值中的54个跟随符|例如| 0 | 0 | 3 | 4 | 5 |并以〜结尾。 如果我有一个ID,例如如何从末尾选择第三个值ID = 54我想选择3;

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:0)

您可以使用Shuumi中的函数将字符串拆分为行,并使用其他问题的代码将拆分的行拆分为列。然后在表中有数据,就可以正常选择:

;WITH Split_Names (ElementID,Element, xmlname)
AS
(
    SELECT ElementID,
    Element,
    CONVERT(XML,'<Names><name>'  
    + REPLACE(Element,'|', '</name><name>') + '</name></Names>') AS xmlname
      FROM [dbo].[func_Split] ('57|0|0|2|||~56|0|0|2|||~55|0|0|2|||~54|0|0|3|4|5|~53|0|0|4|||~52|0|0|4|||~51|0|0|2|||~','~') 
)

 SELECT Element,      
 xmlname.value('/Names[1]/name[1]','varchar(100)') AS ID,    
 xmlname.value('/Names[1]/name[2]','varchar(100)') AS Element1,    
 xmlname.value('/Names[1]/name[3]','varchar(100)') AS Element2,    
 xmlname.value('/Names[1]/name[4]','varchar(100)') AS Element3,    
 xmlname.value('/Names[1]/name[5]','varchar(100)') AS Element4,    
 xmlname.value('/Names[1]/name[6]','varchar(100)') AS Element5    
 INTO #tmp
 FROM Split_Names

 SELECT Element3 FROM #tmp WHERE ID = 54

答案 1 :(得分:0)

您可以将字符串转换为xml,然后从中获取元素。

select 
split.xmlTable.value('v[1]', 'int') as col1,
split.xmlTable.value('v[4]', 'int') as col4
from (
   select cast(('<x><v>' +  replace(replace(col, '~', '</v></x><x><v>'), '|', '</v><v>') + '</v></x>') as xml) as xmlValue
   from yourtable
) as xmlTable
cross apply xmlValue.nodes ('/x') as split(xmlTable)
where split.xmlTable.value('v[1]', 'int') = 54

在Sqlfiddle上here进行测试

答案 2 :(得分:0)

使用这样的数据模型,您将拥有非常复杂且缓慢的查询。这将解决该问题,我强烈建议您对模型进行修改。

这将解决它:

DECLARE @t TABLE(x varchar(max))
INSERT @t 
VALUES
('57|0|0|2|||~56|0|0|2|||~55|0|0|2|||~54|0|0|3|4|5|~53|0|0|4|||~52|0|0|4|||~51|0|0|2|'),
('57|0|0|2|||~56|0|0|2|||~55|0|0|2|||~54|0|0|5|4|5|~53|0|0|4|||~52|0|0|4|||~51|0|0|2|')

DECLARE @pos INT = 3
DECLARE @element INT = 54

;WITH CTE as
(
  SELECT t.c.value('.', 'VARCHAR(2000)') substr
  FROM (
      SELECT x = CAST('<t>' + 
        REPLACE(REPLACE(x, '|', '/'), '~', '</t><t>') + '</t>' AS XML)
      FROM @t
) a
CROSS APPLY x.nodes('/t') t(c)
), CTE2 as
(
  SELECT substr
  FROM CTE
  WHERE 
    cast(concat('<x>',
      REPLACE(substr, '/', '</x><x>'
        ), '</x>') as xml).value('/x[1]','int') = @element
), CTE3 as
(
  SELECT
    t.c.value('.', 'int') val,
    row_number() over(partition by z order by 1/0) - 1 pos
  FROM (
      SELECT x = CAST('<t>' + 
          REPLACE(substr, '/', '</t><t>') + '</t>' AS XML),
          row_number() over(order by 1/0) z
      FROM CTE2
  ) a
  CROSS APPLY x.nodes('/t') t(c)
)
SELECT val
FROM CTE3
WHERE pos = @pos