删除sqlserver中字符串中的前导零

时间:2017-02-09 09:23:47

标签: sql sql-server

我想删除varchar列的前导零。实际上我们将版本信息存储在一列中。查找以下示例版本。

2.00.001
输出将是:2.0.1

输入:2.00.00.001
输出将是:2.0.0.1

输入:2.00
输出将是:2.0

版本列中的点不是常量。它可能是两个,三个或四个

我在谷歌找到了一些解决方案,但那些都没有用。以下是我试过的查询。

SELECT SUBSTRING('2.00.001', PATINDEX('%[^0 ]%', '2.00.001' + ' '), LEN('2.00.001'))

SELECT REPLACE(LTRIM(REPLACE('2.00.001', '0', ' ')),' ', '0')

请在sqlserver中建议我最好的方法。

7 个答案:

答案 0 :(得分:2)

一种方法是使用字符串拆分功能cross applyfor xml pathstuff
有关如何将stuff和for xml一起工作以连接所选行的字符串的解释,read this SO post

使用字符串拆分功能可以将字符串的每个数字部分转换为int,这将删除前导零。对字符串拆分函数的结果执行select语句将使您能够将int值返回到varchar值,由dot分隔。 stuff函数将删除第一个点。

创建字符串拆分功能:

CREATE FUNCTION SplitStrings_XML
(
   @List       NVARCHAR(MAX),
   @Delimiter  NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
   RETURN 
   (  
      SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
      FROM 
      ( 
        SELECT x = CONVERT(XML, '<i>' 
          + REPLACE(@List, @Delimiter, '</i><i>') 
          + '</i>').query('.')
      ) AS a CROSS APPLY x.nodes('i') AS y(i)
   );
GO

我选择使用基于xml的功能,因为它非常简单。如果您使用的是2016版本,则可以使用内置的string_split功能。对于早期版本,我强烈建议阅读Aaron Bertrand的Split strings the right way – or the next best way

创建并填充样本表(在将来的问题中保存此步骤)

DECLARE @T AS TABLE
(
    col varchar(20)
)

INSERT INTO @T VALUES
('2.00.001'),
('2.00.00.001'),
('2.00')

查询:

SELECT col, result
FROM @T
CROSS APPLY 
(
    SELECT STUFF(
    (
    SELECT '.' + CAST(CAST(Item as int) as varchar(20)) 
    FROM SplitStrings_XML(col, '.')
    FOR XML PATH('')
    )
    , 1, 1, '') As result

) x

结果:

col             result
2.00.001        2.0.1
2.00.00.001     2.0.0.1
2.00            2.0

您可以在this link on rextester

上看到它的实际效果

答案 1 :(得分:1)

不需要分割/分析功能,如果可以有超过5组

,则易于扩展
foreach (DataGridViewRow row in GridView1.SelectedRows)
{
  string currentRow = string.Empty;
  currentRow += String.Format("{0} ", row.Cells["MobileNumber"].FormattedValue.ToString());
  selectedRows.Add(currentRow);
}

返回

Declare @YourTable table (YourCol varchar(25))
Insert Into @YourTable Values
('2.00.001'),
('2.00.00.001'),
('2.00')

Update @YourTable
       Set YourCol = concat(Pos1,'.'+Pos2,'.'+Pos3,'.'+Pos4,'.'+Pos5)
 From  @YourTable A
 Cross Apply (
                Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','int')))
                      ,Pos2 = ltrim(rtrim(xDim.value('/x[2]','int')))
                      ,Pos3 = ltrim(rtrim(xDim.value('/x[3]','int')))
                      ,Pos4 = ltrim(rtrim(xDim.value('/x[4]','int')))
                      ,Pos5 = ltrim(rtrim(xDim.value('/x[5]','int')))
                From  (Select Cast('<x>' + replace((Select replace(A.YourCol,'.','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as A 
             ) B

Select * from @YourTable

答案 2 :(得分:1)

简单,快速,兼容和可读的方式 - 没有表格或XML技巧。

正确处理所有情况,包括空字符串,NULL00100等数字 支持无限数量的群组。在所有SQL Server版本上运行。

  • 步骤1:从所有组中删除前导零。

  • 步骤2:将单个零置于没有数字的组。

[编辑:不知道为什么它被投票两次。检查解决方案:]

功能:

CREATE FUNCTION dbo.fncGetNormalizedVersionNumber(@Version nvarchar(200))
    RETURNS nvarchar(200) AS
BEGIN
    -- Preprocessing: Surround version string by dots so all groups have the same format.
    SET @Version = '.' + @Version + '.';

    -- Step 1: Remove any leading zeros from groups as long as string length decreases.
    DECLARE @PreviousLength int = 0;
    WHILE @PreviousLength <> LEN(@Version)
    BEGIN
        SET @PreviousLength = LEN(@Version);
        SET @Version = REPLACE(@Version, '.0', '.');
    END;

    -- Step 2: Insert 0 to any empty group as long as string length increases.
    SET @PreviousLength = 0;
    WHILE @PreviousLength <> LEN(@Version)
    BEGIN
        SET @PreviousLength = LEN(@Version);
        SET @Version = REPLACE(@Version, '..', '.0.');
    END;

    -- Strip leading and trailing dot added by preprocessing.
    RETURN SUBSTRING(@Version, 2, LEN(@Version) - 2);
END;

<强>用法:

SELECT dbo.fncGetNormalizedVersionNumber('020.00.00.000100');
  

20.0.0.100

每100,000次计算的效果:

答案 3 :(得分:1)

对于SQL Server 2016:

SELECT STUFF ((SELECT '.' + CAST(CAST(value AS INT) AS VARCHAR) FROM STRING_SPLIT('2.00.001', '.') FOR XML PATH ('')) , 1, 1, '')

根据这个:https://sqlperformance.com/2016/03/sql-server-2016/string-split

这是最快的方式:) Aaron Bertrand知道它的东西。

有关在SQL Server上拆分字符串的有趣且深入的阅读请阅读以下知识:http://www.sqlservercentral.com/articles/Tally+Table/72993/

它有一些聪明的策略

答案 4 :(得分:0)

试试这个

SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col))

答案 5 :(得分:0)

我不确定这是你在找什么,但你可以放手一搏,它最多可以处理4个零。

DECLARE @VERSION NVARCHAR(20) = '2.00.00.001'
SELECT REPLACE(REPLACE(REPLACE(@VERSION, '0000','0'),'000','0'),'00','0')

2.0.0.01

SET @VERSION = '2.00.00.01'
SELECT REPLACE(REPLACE(REPLACE(@VERSION, '0000','0'),'000','0'),'00','0')

2.0.0.01

SET @VERSION = '2.000.0000.0001'
SELECT REPLACE(REPLACE(REPLACE(@VERSION, '0000','0'),'000','0'),'00','0')

2.0.0.01

答案 6 :(得分:0)

这是另一个样本:

CREATE TABLE #tt(s VARCHAR(15))
INSERT INTO  #tt VALUES
('2.00.001'),
('2.00.00.001'),
('2.00')

SELECT t.s,STUFF(c.s,1,1,'') AS news FROM #tt AS t
OUTER APPLY(
       SELECT '.'+LTRIM(z.n) FROM (VALUES(CONVERT(XML,'<n>'+REPLACE(t.s,'.','</n><n>')+'</n>'))) x(xs)
       CROSS APPLY(SELECT n.value('.','int') FROM x.xs.nodes('n') AS y(n)) z(n)
       FOR XML PATH('')
) c(s)
s               news
--------------- -----------
2.00.001        2.0.1
2.00.00.001     2.0.0.1
2.00            2.0