我想删除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中建议我最好的方法。
答案 0 :(得分:2)
一种方法是使用字符串拆分功能cross apply
,for xml path
和stuff
。
有关如何将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
上看到它的实际效果
答案 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)
正确处理所有情况,包括空字符串,NULL
或00100
等数字
支持无限数量的群组。在所有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