Funkcja PadLeft w T-SQL


113

Mam następującą tabelę A:

id
----
1
2
12
123
1234

Muszę uzupełnić idwartości z lewej strony zerami:

id
----
0001
0002
0012
0123
1234

Jak mogę to osiągnąć?

Odpowiedzi:


197

Myślę, że to może być to, czego szukasz:

SELECT padded_id = REPLACE(STR(id, 4), SPACE(1), '0') 

FROM tableA

lub

SELECT REPLACE(STR(id, 4), SPACE(1), '0') AS [padded_id]

FROM tableA

Nie testowałem składni w drugim przykładzie. Nie jestem pewien, czy to działa w 100% - może wymagać pewnych poprawek - ale przekazuje ogólną ideę, jak uzyskać pożądany wynik.

EDYTOWAĆ

Aby rozwiązać problemy wymienione w komentarzach ...

@ pkr298 - Tak STR działa tylko na liczbach ... Pole OP to ID ... stąd tylko liczba.

@Desolator - Oczywiście to nie zadziała ... Pierwszy parametr ma 6 znaków. Możesz zrobić coś takiego:

SELECT REPLACE(STR(id,
(SELECT LEN(MAX(id)) + 4 FROM tableA)), SPACE(1), '0') AS [padded_id] FROM tableA

teoretycznie powinno to przesunąć słupki bramki ... ponieważ liczba rośnie, ZAWSZE powinno działać ... niezależnie od tego, czy jest 1 czy 123456789 ...

Więc jeśli twoja maksymalna wartość to 123456 ... zobaczysz 0000123456, a jeśli twoja minimalna wartość to 1, zobaczysz 0000000001


4
STR () działa tylko na liczbach (lub liczbach w polach łańcuchowych). Ten kod zepsuje się, jeśli używasz go w polu varchar, które zakładasz, że ma liczbę, ale jeden z rekordów zawiera złe (nieliczbowe) dane. W tym przypadku funkcja RIGHT () nie ulegnie awarii.
pkr298,

1
Funkcja STR () nie będzie działać, jeśli liczba jest większa długość (np STR(123456, 4)powróci****

2
@Desolator Dodałem odpowiedź i poprawkę, aby ułatwić dodany scenariusz.
Patrick,

67

SQL Server obsługuje teraz funkcję FORMAT począwszy od wersji 2012, więc:

SELECT FORMAT(id, '0000') FROM TableA

da rade.

Jeśli Twój identyfikator lub kolumna jest w a varchari przedstawia liczbę, którą najpierw przekonwertujesz:

SELECT FORMAT(CONVERT(INT,id), '0000') FROM TableA

Zręczne i proste, dzięki! Biorąc pod uwagę datę pierwotnego pytania, powinna to być teraz oficjalna odpowiedź;)
David Gunderson

1
Jeśli id ​​jest ciągiem, możesz najpierw przekonwertować go na liczbę całkowitą - wybierz format (convert (int, id), '0000')
CrimsonKing

Przepraszam, ale głosuję przeciw, ponieważ ta droga jest NAPRAWDĘ powolna. Przejechanie 90 rzędów zajęło całe cztery sekundy, podczas gdy zaakceptowana odpowiedź była natychmiastowa. Jest to bardzo poważna wada, a FORMAT powinien być używany tylko na jednym lub dwóch rekordach, maks. W przeciwnym razie jest bezużyteczny ze względu na bardzo słabą wydajność.
Shadow Wizard is Ear For You

@ShadowWizard Widzę natychmiastową wydajność przy użyciu FORMATU z tysiącami wierszy.
JohnnyHK,

@JohnnyHK no może coś z projektem tabeli lub innymi dziwactwami db, ale mimo to ... faktem jest, że dla mnie było to bardzo wolne, podczas gdy w drugą stronę było szybkie.
Shadow Wizard is Ear For You


43

Stary post, ale może to komuś pomoże:

Aby zakończyć, dopóki nie skończy się 4 niepustymi znakami:

SELECT RIGHT ('0000'+COLUMNNAME, 4) FROM TABLENAME;

Aby ukończyć do 10:

SELECT RIGHT ('0000000000'+COLUMNNAME, 10) FROM TABLENAME;

Jeśli kolumna jest numeryczna , najpierw przekonwertuj ją na varchar z takim kodem:

Select RIGHT('0000'+Convert(nvarchar(20), COLUMNNAME), 4)
From TABLENAME

Aby uzupełnić do 10 z polem numerycznym:

SELECT RIGHT ('0000000000'+Convert(nvarchar(20), COLUMNNAME), 10) FROM TABLENAME;

1
@ SilverM-A nie ma narzędzia do dodawania 0 przed liczbą, ponieważ i tak zostaną one zignorowane (w końcu 0003 to 3). Prawdopodobnie to, co chcesz osiągnąć, to rzutowanie tej liczby na łańcuch (varchar), a następnie użycie powyższej instrukcji.
Marcelo Myara

1
@ SilverM-A, jeśli tak jest, po prostu rzuć go za pomocą polecenia „CAST”, takiego jak: SELECT RIGHT ('0000000000' + CAST (COLUMNNAME AS VARCHAR), 10) FROM TABLENAME; Czy to to?
Marcelo Myara

@MarceloMyara to powinna być część odpowiedzi, a nie tylko komentarz. Dodałem teraz siebie.
Shadow Wizard is Ear For You

Uwaga: to najbardziej wydajna odpowiedź, bez wymyślnych funkcji, które mogą działać bardzo wolno. Dlatego dałem mu dodatkową nagrodę.
Shadow Wizard is Ear For You

12

Spróbuj tego:

SELECT RIGHT(REPLICATE('0',4)+CAST(Id AS VARCHAR(4)),4) FROM [Table A]


5

Działa to w przypadku łańcuchów, liczb całkowitych i liczb:

SELECT CONCAT(REPLICATE('0', 4 - LEN(id)), id)

Gdzie 4jest pożądana długość. Działa dla liczb z więcej niż 4 cyframi, zwraca pusty ciąg dla NULLwartości.


3

Jeśli ktoś nadal jest zainteresowany, znalazłem ten artykuł na DATABASE.GUIDE:
Left Padding in SQL Server - 3 LPAD () Equivalents

Krótko mówiąc, w tym artykule wymieniono 3 metody.
Powiedzmy, że Twój identyfikator = 12 i chcesz, aby był wyświetlany jako 0012.

Metoda 1 - użycie funkcji RIGHT ()
Pierwsza metoda używa funkcji RIGHT () do zwrócenia tylko prawej części ciągu, po dodaniu kilku wiodących zer.

SELECT RIGHT('00' + '12', 4);

Wynik:
0012

Metoda 2 - użyj kombinacji RIGHT () i REPLICATE ()
Ta metoda jest prawie taka sama jak poprzednia, z tą różnicą, że po prostu zastępuję trzy zera funkcją REPLICATE ():

SELECT RIGHT(REPLICATE('0', 2) + '12', 4);

Wynik:
0012

Metoda 3 - Użyj kombinacji REPLACE () i STR ()
Ta metoda pochodzi z zupełnie innego punktu widzenia niż poprzednie metody:

SELECT REPLACE(STR('12', 4),' ','0');

Wynik:
0012

Sprawdź artykuł, jest bardziej dogłębna analiza z przykładami.


2

To jest to, czego zwykle używam, gdy potrzebuję uzupełnić wartość.

SET @PaddedValue = REPLICATE('0', @Length - LEN(@OrigValue)) + CAST(@OrigValue as VARCHAR)

1

Potrzebowałem tego w funkcji na serwerze SQL i poprawiłem nieco odpowiedź Patryka.

declare @dossierId int = 123
declare @padded_id varchar(7)


set @padded_id = REPLACE(
              SPACE(7 - LEN(@dossierId)) + convert(varchar(7), @dossierId), 
              SPACE(1),  
              '0') 

SELECT @dossierId as '@dossierId'
      ,SPACE(LEN(@dossierId)) + convert(varchar(7)
      ,@dossierId) as withSpaces
      ,@padded_id as '@padded_id'

1

Utwórz funkcję:

    Create FUNCTION [dbo].[PadLeft]
      (
        @Text NVARCHAR(MAX) ,
        @Replace NVARCHAR(MAX) ,
        @Len INT
      )
RETURNS NVARCHAR(MAX)
AS
    BEGIN 


        DECLARE @var NVARCHAR(MAX) 

        SELECT @var = ISNULL(LTRIM(RTRIM(@Text)) , '')


        RETURN   RIGHT(REPLICATE(@Replace,@Len)+ @var, @Len)


    END

Przykład:

Select dbo.PadLeft('123456','0',8)

Jeszcze uwaga na temat standardów, nie zawracałbym sobie głowy sprawdzaniem IsNull, jeśli wartość jest równa null, funkcja powinna nadal zwracać wartość null dla tej wartości, ponieważ jest to standardowe zachowanie funkcji wbudowanych. Jeśli przekonwertujemy wszystko na wartość różną od null, wywołujący nie będzie już mógł używać operacji logicznych o wartości null, których w przeciwnym razie oczekiwałby. (Null w wielu moich tabelach oznacza „nie określono” i należy użyć wartości domyślnej.SELECT @var = LTRIM(RTRIM(@Text))
Chris Schaller

1

Stworzyłem funkcję:

CREATE FUNCTION [dbo].[fnPadLeft](@int int, @Length tinyint)
RETURNS varchar(255) 
AS 
BEGIN
    DECLARE @strInt varchar(255)

    SET @strInt = CAST(@int as varchar(255))
    RETURN (REPLICATE('0', (@Length - LEN(@strInt))) + @strInt);
END;

Użyj: wybierz dbo.fnPadLeft (123, 10)

Zwroty: 0000000123


0

Coś całkiem zgodnego z ODBC w razie potrzeby może wyglądać następująco:

select ifnull(repeat('0', 5 - (floor(log10(FIELD_NAME)) + 1)), '')
        + cast (FIELD as varchar(10))
  from TABLE_NAME

Wynika to z faktu, że liczbę cyfr dla liczby o podstawie 10 można znaleźć przez integralną składową jej dziennika. Z tego możemy odjąć go od żądanej szerokości wypełnienia. Powtórzenie zwróci nullwartości poniżej 1, więc potrzebujemy ifnull.


0

Moje rozwiązanie nie jest wydajne, ale pomogło mi w sytuacji, gdy wartości (numery czeków bankowych i nr ref. Przelewu) były przechowywane jako varchar, gdzie niektóre wpisy miały wartości alfanumeryczne i musiałem dopełniać, jeśli długość jest mniejsza niż 6 znaków.

Pomyśl o udostępnieniu, jeśli ktoś znajdzie się w tej samej sytuacji

declare @minlen int = 6
declare @str varchar(20)

set @str = '123'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: 000123

set @str = '1234'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: 001234

set @str = '123456'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: 123456

set @str = '123456789'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: 123456789

set @str = '123456789'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: 123456789


set @str = 'NEFT 123456789'
select case when len(@str) < @minlen then REPLICATE('0',@minlen-len(@str))+@str else @str end
--Ans: NEFT 123456789

0

Prostym przykładem może być

    DECLARE @number INTEGER
    DECLARE @length INTEGER
    DECLARE @char   NVARCHAR(10)
    SET @number = 1
    SET @length = 5
    SET @char = '0'

    SELECT FORMAT(@number, replicate(@char, @length))

0

Stworzyłem w tym celu funkcję, w której możesz określić żądaną długość znaków wyjściowych:

CREATE FUNCTION [dbo].[udfLeadingZero]
(
        @String VARCHAR(MAX)
,       @Len INT
)
RETURNS VARCHAR(MAX)
BEGIN
    SET @String = RIGHT(REPLICATE('0',@Len)+@String,@Len)
RETURN @String
END
GO

Przykładowe wyniki


-5

Bardziej wydajnym sposobem jest:

Select id, LEN(id)
From TableA
Order by 2,1 

The result :
id
----
1
2
12
123
1234

6
Jak to odpowiada na pytanie PO dotyczące wypełniania zerami?
Filburt
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.