Ik gebruik dit Al geruime tijd:
SUBSTRING(str_col, PATINDEX('%[^0]%', str_col), LEN(str_col))
Eén onlangs heb ik een probleem met kolommen gevonden met alle “0” -karakters zoals ‘00000000’ omdat het nooit een niet-“0” -karakter vindt om te matchen.
Een alternatieve techniek die ik heb gezien, is het gebruik TRIM
:
REPLACE(LTRIM(REPLACE(str_col, '0', ' ')), ' ', '0')
Dit heeft een probleem als er embedded spaties zijn, omdat ze worden omgezet in “0” s wanneer de spaties terug worden ingeschakeld in “0”.
Ik probeer een scalaire UDF te vermijden. Ik heb veel prestatieproblemen gevonden met UDFS in SQL Server 2005.
Antwoord 1, Autoriteit 100%
SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col))
Antwoord 2, Autoriteit 16%
Waarom spookt u niet zojuist de waarde op INTEGER
en vervolgens terug naar VARCHAR
?
SELECT CAST(CAST('000000000' AS INTEGER) AS VARCHAR)
--------
0
Antwoord 3, Autoriteit 4%
Andere antwoorden hier om niet in aanmerking te nemen als u alle nul’s (of zelfs een enkele nul) hebt.
Sommigen standaard een lege reeks naar nul, die verkeerd is wanneer het zou moeten blijven.
Lees de oorspronkelijke vraag opnieuw. Dit beantwoordt wat de vraagsteller wil.
Oplossing # 1:
--This example uses both Leading and Trailing zero's.
--Avoid losing those Trailing zero's and converting embedded spaces into more zeros.
--I added a non-whitespace character ("_") to retain trailing zero's after calling Replace().
--Simply remove the RTrim() function call if you want to preserve trailing spaces.
--If you treat zero's and empty-strings as the same thing for your application,
-- then you may skip the Case-Statement entirely and just use CN.CleanNumber .
DECLARE @WackadooNumber VarChar(50) = ' 0 0123ABC D0 '--'000'--
SELECT WN.WackadooNumber, CN.CleanNumber,
(CASE WHEN WN.WackadooNumber LIKE '%0%' AND CN.CleanNumber = '' THEN '0' ELSE CN.CleanNumber END)[AllowZero]
FROM (SELECT @WackadooNumber[WackadooNumber]) AS WN
OUTER APPLY (SELECT RTRIM(RIGHT(WN.WackadooNumber, LEN(LTRIM(REPLACE(WN.WackadooNumber + '_', '0', ' '))) - 1))[CleanNumber]) AS CN
--Result: "123ABC D0"
Oplossing # 2 (met voorbeeldgegevens):
SELECT O.Type, O.Value, Parsed.Value[WrongValue],
(CASE WHEN CHARINDEX('0', T.Value) > 0--If there's at least one zero.
AND LEN(Parsed.Value) = 0--And the trimmed length is zero.
THEN '0' ELSE Parsed.Value END)[FinalValue],
(CASE WHEN CHARINDEX('0', T.Value) > 0--If there's at least one zero.
AND LEN(Parsed.TrimmedValue) = 0--And the trimmed length is zero.
THEN '0' ELSE LTRIM(RTRIM(Parsed.TrimmedValue)) END)[FinalTrimmedValue]
FROM
(
VALUES ('Null', NULL), ('EmptyString', ''),
('Zero', '0'), ('Zero', '0000'), ('Zero', '000.000'),
('Spaces', ' 0 A B C '), ('Number', '000123'),
('AlphaNum', '000ABC123'), ('NoZero', 'NoZerosHere')
) AS O(Type, Value)--O is for Original.
CROSS APPLY
( --This Step is Optional. Use if you also want to remove leading spaces.
SELECT LTRIM(RTRIM(O.Value))[Value]
) AS T--T is for Trimmed.
CROSS APPLY
( --From @CadeRoux's Post.
SELECT SUBSTRING(O.Value, PATINDEX('%[^0]%', O.Value + '.'), LEN(O.Value))[Value],
SUBSTRING(T.Value, PATINDEX('%[^0]%', T.Value + '.'), LEN(T.Value))[TrimmedValue]
) AS Parsed
Resultaten:
Samenvatting:
Je zou kunnen gebruiken wat ik hierboven heb voor een eenmalige verwijdering van voorloopnullen.
Als je van plan bent om het veel te hergebruiken, plaats het dan in een Inline-Table-Valued-Function (ITVF).
Uw zorgen over prestatieproblemen met UDF’s zijn begrijpelijk.
Dit probleem is echter alleen van toepassing op All-Scalar-Functions en Multi-Statement-Table-Functions.
Het gebruik van ITVF’s is prima.
Ik heb hetzelfde probleem met onze database van derden.
Met alfanumerieke velden worden er veel ingevoerd zonder de voorloopspaties, verdorie mensen!
Dit maakt samenvoegen onmogelijk zonder de ontbrekende voorloopnullen op te ruimen.
Conclusie:
In plaats van de voorloopnullen te verwijderen, kunt u overwegen om uw getrimde waarden op te vullen met voorloopnullen wanneer u uw joins uitvoert.
Beter nog, ruim uw gegevens in de tabel op door voorloopnullen toe te voegen en vervolgens uw indexen opnieuw op te bouwen.
Ik denk dat dit VEEL sneller en minder complex zou zijn.
SELECT RIGHT('0000000000' + LTRIM(RTRIM(NULLIF(' 0A10 ', ''))), 10)--0000000A10
SELECT RIGHT('0000000000' + LTRIM(RTRIM(NULLIF('', ''))), 10)--NULL --When Blank.
Antwoord 4, autoriteit 2%
In plaats van een ruimte vervangen de 0’s met een ‘zeldzaam’ witruimtekarakter dat normaal niet in de tekst van de kolom zou moeten zijn. Een lijnvoeding is waarschijnlijk goed genoeg voor een kolom als deze. Dan kun je Normaal ltrim en het speciale teken vervangen door 0’s weer.
Antwoord 5
Het volgende zal ‘0’ terugkeren als de string volledig bestaat uit Nullen:
CASE WHEN SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col)) = '' THEN '0' ELSE SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col)) END AS str_col
Antwoord 6
Dit maakt een mooie functie ….
DROP FUNCTION [dbo].[FN_StripLeading]
GO
CREATE FUNCTION [dbo].[FN_StripLeading] (@string VarChar(128), @stripChar VarChar(1))
RETURNS VarChar(128)
AS
BEGIN
-- http://stackoverflow.com/questions/662383/better-techniques-for-trimming-leading-zeros-in-sql-server
DECLARE @retVal VarChar(128),
@pattern varChar(10)
SELECT @pattern = '%[^'[email protected]+']%'
SELECT @retVal = CASE WHEN SUBSTRING(@string, PATINDEX(@pattern, @string+'.'), LEN(@string)) = '' THEN @stripChar ELSE SUBSTRING(@string, PATINDEX(@pattern, @string+'.'), LEN(@string)) END
RETURN (@retVal)
END
GO
GRANT EXECUTE ON [dbo].[FN_StripLeading] TO PUBLIC
Antwoord 7
Gegoten (waarde als int) werkt altijd als een cijfer een cijfer
is
Antwoord 8
Mijn versie hiervan is een aanpassing van het werk van Arvo, met een beetje meer toegevoegd om twee andere gevallen te garanderen.
1) Als we alle 0s hebben, moeten we het cijfer retourneren 0.
2) Als we een blanco hebben, moeten we nog steeds een leeg teken retourneren.
CASE
WHEN PATINDEX('%[^0]%', str_col + '.') > LEN(str_col) THEN RIGHT(str_col, 1)
ELSE SUBSTRING(str_col, PATINDEX('%[^0]%', str_col + '.'), LEN(str_col))
END
Antwoord 9
replace(ltrim(replace(Fieldname.TableName, '0', '')), '', '0')
De suggestie van Thomas G werkte voor onze behoeften.
Het veld in ons geval was al een string en alleen de voorloopnullen moesten worden bijgesneden. Meestal is het allemaal numeriek, maar soms zijn er letters zodat de vorige INT-conversie crashte.
Antwoord 10
SELECT CAST(CAST('000000000' AS INTEGER) AS VARCHAR)
Dit heeft een limiet voor de lengte van de string die kan worden geconverteerd naar een INT
Antwoord 11
Als u Snowflake SQL gebruikt, kunt u dit gebruiken:
ltrim(str_col,'0')
De ltrim-functie verwijdert alle instanties van de aangewezen set tekens aan de linkerkant.
Dus ltrim(str_col,’0′) op ‘00000008A’ zou ‘8A’ retourneren
En rtrim(str_col,’0.’) op ‘$125.00’ zou ‘$125’ opleveren
Antwoord 12
Probeer dit:
replace(ltrim(replace(@str, '0', ' ')), ' ', '0')
Antwoord 13
Als je niet wilt converteren naar int, geef ik de voorkeur aan onderstaande logica omdat het nulls aankan
IFNULL(veld;LTRIM(veld;’0′))
Antwoord 14
SUBSTRING(str_col, IIF(LEN(str_col) > 0, PATINDEX('%[^0]%', LEFT(str_col, LEN(str_col) - 1) + '.'), 0), LEN(str_col))
Werkt prima, zelfs met ‘0’, ’00’ enzovoort.
Antwoord 15
Voor het converteren van getallen als varcharnaar intkunt u ook eenvoudig
gebruiken
(column + 0)
Antwoord 16
Dit kan helpen
SELECT ABS(column_name) FROM [db].[schema].[table]
Antwoord 17
In MySQL kunt u dit doen…
Trim(Leading '0' from your_column)