how to convert string format - sql

How can I convert a number to a formatted string of fixed length in SQL Server 2005 using T-SQL?
e.g.
Inputs: 5,01,007,0009,00011,01200
Result: 000005,000007,000009,0000011,001200

Looks like you want it 6 wide. Try putting your pad characters, in this case, zeros, to the left of your int/string, and then take the 6 chars on the right side of the string.
How about this?
DECLARE #i int;
SELECT #i = 1200;
SELECT RIGHT('000000'+ CAST(#i as varchar(10)), 6);

The best way I've found to do this is using the STR statement:
SELECT REPLACE(STR(123, 6), ' ', '0')
The above statement will result in 000123. It basically converts 123 to a string of 6 characters (padded with spaces), then uses REPLACE to replace the spaces with zeros.

TRY THIS
WITH t(c) AS
(
SELECT 1.99 UNION ALL
SELECT 21.34 UNION ALL
SELECT 1797.94 UNION ALL
SELECT 300.36 UNION ALL
SELECT 21.99 UNION ALL
SELECT -2.31
)
select
c,
replicate(0,4-len(replace(substring(cast(c as varchar(10)),1,charindex('.',c)-1),'-','')))+''+
replace(replace(substring(cast(c as varchar(10)),1,charindex('.',c)-1),'-',''),'','-') +''+
replace(substring(cast(c as varchar(10)),charindex('.',c),len(c)),'-','')
from t
i will still optimize it

Best way for dynamic leading zero allocation
WITH t(c) AS ( SELECT 1.99 UNION ALL
SELECT 21.34 UNION ALL SELECT
1797.94 UNION ALL SELECT 300.36 UNION ALL SELECT 21.99 UNION ALL
SELECT 2.31 ),
Final (a,b,c,d) as ( Select c,
substring(cast(c as
varchar(10)),1,charindex('.',c)-1) ,
(select max(len(substring(cast(c as
varchar(10)),1,charindex('.',c)-1)))
from t), substring(cast(c as
varchar(10)),charindex('.',c)+1,len(c))
From t group by c )
select a,
right(replicate('0',c)+''+b,4)+'.'+d
from final

declare #i int
set #i=10
print replace(str(#i),' ','0')

Related

Removing only the leading zero and not all zeros

the goal is to take the numbers in between 2 dashes and I was able to do that but the issue is that I need to remove the leading zero to the returned value. How can I incorporate the LTRIM function or other functions without removing all zeros?
Sample:
123-010-456
Results should be 10
SELECT[Phone],
REPLACE(SUBSTRING([Phone], CHARINDEX('-', [Phone]), CHARINDEX('-', [Phone])),'-','') AS substring
FROM [SalesLT].[Customer]
If your data pattern/format is fixed then below will help
SELECT RIGHT(PARSENAME(REPLACE('123-010-456','-','.'),2),2)
You can combine the following to one query, but for better understanding I break it down to 3 steps.
DECLARE #String nvarchar(20) = '123-010-456'
DECLARE #MiddlePart nvarchar(20)
DECLARE #FirstNonZero int
--Get the middle part
SET #MiddlePart = SUBSTRING(#String,
CHARINDEX('-',#String)+1, --Find the 1st dash
LEN(#String)-CHARINDEX('-',#String)-CHARINDEX('-',Reverse(#String)) --Find length between two dashes
)
--Get the First Non zero number
SET #FirstNonZero = (SELECT MIN(x)
FROM (SELECT CHARINDEX('1',#MiddlePart) as x WHERE CHARINDEX('1',#MiddlePart)>0
UNION
SELECT CHARINDEX('2',#MiddlePart) as x WHERE CHARINDEX('2',#MiddlePart)>0
UNION
SELECT CHARINDEX('3',#MiddlePart) as x WHERE CHARINDEX('3',#MiddlePart)>0
UNION
SELECT CHARINDEX('4',#MiddlePart) as x WHERE CHARINDEX('4',#MiddlePart)>0
UNION
SELECT CHARINDEX('5',#MiddlePart) as x WHERE CHARINDEX('5',#MiddlePart)>0
UNION
SELECT CHARINDEX('6',#MiddlePart) as x WHERE CHARINDEX('6',#MiddlePart)>0
UNION
SELECT CHARINDEX('7',#MiddlePart) as x WHERE CHARINDEX('7',#MiddlePart)>0
UNION
SELECT CHARINDEX('8',#MiddlePart) as x WHERE CHARINDEX('8',#MiddlePart)>0
UNION
SELECT CHARINDEX('9',#MiddlePart) as x WHERE CHARINDEX('9',#MiddlePart)>0
) a)
--Final
Select SUBSTRING(#MiddlePart,#FirstNonZero,LEN(#MiddlePart)-#FirstNonZero+1)
You could try to extract the middle part and convert it to int - this will remove all leading zeroes while keeping the trailing ones... if required, you can then convert it back to varchar. Following an example:
DECLARE #t TABLE(testval nvarchar(40))
INSERT INTO #t VALUES
('123-010-456')
,('1234-1-456789')
,('12-00010-4')
,('1-0007-4')
SELECT *
,SUBSTRING(testval, CHARINDEX('-', testval)+1, CHARINDEX('-', testval, CHARINDEX('-', testval)+1)-CHARINDEX('-', testval)-1)
,CAST(SUBSTRING(testval, CHARINDEX('-', testval)+1, CHARINDEX('-', testval, CHARINDEX('-', testval)+1)-CHARINDEX('-', testval)-1) AS INT)
FROM #t

SQL Trim Preceding zeros

I have an ID that looks like below:
000000000000000091
000000000000000019
000000000000001859
000000000000001220
000000000000001220
000000000000001182
000000000000010156
I am looking to trim the preceeding zero's so only yhe
I need to trim the values so it shows up like below:
91
19
1859
1220
1220
1182
10156
I am trying to do the following:
UPDATE TABLE_NAME SET Material = RTRIM(LTRIM(REPLACE(Material,'0',' '))),' ','0'
You can use Substring with PatIndex without any conversion.
UPDATE TABLE_NAME SET Material = Substring(Material, PatIndex('%[1-9]%',Material),Len(Material))
If the numbers are integers below the 2^63 mark you can use CAST(). For example:
with
t as (
select '000000000000000091' as v
union all select '000000000000000019'
union all select '000000000000001859'
union all select '000000000000001220'
union all select '000000000000001220'
union all select '000000000000001182'
union all select '000000000000010156'
)
select '' + cast(v as bigint) from t
Result:
(No column name)
----------------
91
19
1859
1220
1220
1182
10156
See running example at db<>fiddle.
Can you try casting it to int or bigint?
Something like
UPDATE TABLE_NAME SET Material = CAST(Material AS BIGINT)
For your input
WITH DATA AS
(
SELECT Material
FROM
(
VALUES('000000000000000091'),
('000000000000000019'),
('000000000000001859'),
('000000000000001220'),
('000000000000001220'),
('000000000000001182'),
('000000000000010156')
) Data (Material)
)
SELECT Material, CAST(Material AS BIGINT) AS Material_Output
FROM Data

I want to remove part of string from a string

Thank you in advance.
I want to remove string after . including ., but length is variable and string can be of any length.
1)Example:
Input:- SCC0204.X and FRK0005.X and RF0023.X and ADF1010.A and HGT9010.V
Output: SCC0204 and FRK0005 and RF0023 and ADF1010.A and HGT9010.V
I tried using the charindex but as the length keeps on changing i wasn't able to do it. I want to trim the values with ending with only X
Any help will be greatly appreciated.
Assuming there is only one dot
UPDATE TABLE
SET column_name = left(column_name, charindex('.', column_name) - 1)
For SELECT
select left(column_name, charindex('.', column_name) - 1) AS col
from your_table
Hope this helps. The code only trims the string when the value has a decimal "." in it and if that value is equal to .X
;WITH cte_TestData(Code) AS
(
SELECT 'SCC0204.X' UNION ALL
SELECT 'FRK0005.X' UNION ALL
SELECT 'RF0023.X' UNION ALL
SELECT 'ADF1010.A' UNION ALL
SELECT 'HGT9010.V' UNION ALL
SELECT 'SCC0204' UNION ALL
SELECT 'FRK0005'
)
SELECT CASE
WHEN CHARINDEX('.', Code) > 0 AND RIGHT(Code,2) = '.X'
THEN SUBSTRING(Code, 1, CHARINDEX('.', Code) - 1)
ELSE Code
END
FROM cte_TestData
If the criteria is only to replace remove .X then probably this should also work
;WITH cte_TestData(Code) AS
(
SELECT 'SCC0204.X' UNION ALL
SELECT 'FRK0005.X' UNION ALL
SELECT 'RF0023.X' UNION ALL
SELECT 'ADF1010.A' UNION ALL
SELECT 'HGT9010.V' UNION ALL
SELECT 'SCC0204' UNION ALL
SELECT 'FRK0005'
)
SELECT REPLACE (Code,'.X','')
FROM cte_TestData
Use LEFT String function :
DECLARE #String VARCHAR(100) = 'SCC0204.XXXXX'
SELECT LEFT(#String,CHARINDEX('.', #String) - 1)
I think your best bet here is to create a function that parses the string and uses regex. I hope this old post helps:
Perform regex (replace) in an SQL query
However, if the value you need to trim is constantly ".X", then you should use
select replace(string, '.x', '')
Please check the below code. I think this will help you.
DECLARE #String VARCHAR(100) = 'SCC0204.X'
IF (SELECT RIGHT(#String,2)) ='.X'
SELECT LEFT(#String,CHARINDEX('.', #String) - 1)
ELSE
SELECT #String
Update: I just missed one of the comments where the OP clarifies the requirement. What I put together below is how you would deal with a requirement to remove everything after the first dot on strings ending with X. I leave this here for reference.
;WITH cte_TestData(Code) AS
(
SELECT 'SCC0204.X' UNION ALL -- ends with '.X'
SELECT 'FRK.000.X' UNION ALL -- ends with '.X', contains multiple dots
SELECT 'RF0023.AX' UNION ALL -- ends with '.AX'
SELECT 'ADF1010.A' UNION ALL -- ends with '.A'
SELECT 'HGT9010.V' UNION ALL -- ends with '.V'
SELECT 'SCC0204.XF' UNION ALL -- ends with '.XF'
SELECT 'FRK0005' UNION ALL -- totally clean
SELECT 'ABCX' -- ends with 'X', not dots
)
SELECT
orig_string = code,
newstring =
SUBSTRING
(
code, 1,
CASE
WHEN code LIKE '%X'
THEN ISNULL(NULLIF(CHARINDEX('.',code)-1, -1), LEN(code))
ELSE LEN(code)
END
)
FROM cte_TestData;
FYI - SQL Server 2012+ you could simplify this code like this:
SELECT
orig_string = code,
newstring =
SUBSTRING(code, 1,IIF(code LIKE '%X', ISNULL(NULLIF(CHARINDEX('.',code)-1, -1), LEN(code)), LEN(code)))
FROM cte_TestData;
With SUBSTRING you can achieve your requirements by below code.
SELECT SUBSTRING(column_name, 0, CHARINDEX('.', column_name)) AS col
FROM your_table
If you want to remove fixed .X from string you can also use REPLACE function.
SELECT REPLACE(column_name, '.X', '') AS col

SQL to generate next sequence in an alphanumeric id

I gained some help from this question, but still need some further assistance.
I need to be able to generate the next available 2-digit alphanumeric code. I cannot change the table definition, before you ask. I am working in T-SQL.
So, for example, let's say I have the sequence
00, 01, 02,..., 09, 0A, 0B, 0C,..., 0Y, 0Z, 10, 11,...1Y, 1Z, 20, 21,..., 9Y, 9Z, I would like for the next id to be A0,
then A1, A2, ..., A9, AA, AB, AC, ..., AZ, I would like for the next id to be B0, then B1, etc.
So, in short, I would like to go from 00 all the way to ZZ and each time look for the MAX in that field and assign a new code 1 greater than the max. I would understand that A > 9, and the first column greater than the second, so A0 > 99 and AA > A9.
I wish I could just assign a numeric id to all of this, but the table definition is more critical at this point and so I'm not allowed to change it, so I am trying to maximize the available ids I'll have in such a limited space.
Thank you for your help.
Have a look at this. This is a really nasty problem for ID's. You've effectively limited yourself a low number of permutations of the key with 2 characters. Also you have a problem that you'll need to deal with if ZZ is used and this algorithm runs again. I have expanded these into as logical steps as possible for demonstration, but feel free to condense as needed.
DECLARE #ExistingTable TABLE (ID CHAR(2))
INSERT INTO #ExistingTable (ID) VALUES ('5A'),('5B')
DECLARE #NewID CHAR(2)
;WITH
Ranks AS (
SELECT '0' AS [Character] UNION SELECT '1' AS [Character] UNION SELECT '2' UNION SELECT '3' UNION SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT 'A' UNION SELECT 'B'UNION
SELECT 'C' UNION SELECT 'D' UNION SELECT 'E' UNION SELECT 'F' UNION SELECT 'G' UNION SELECT 'H' UNION
SELECT 'I' UNION SELECT 'J' UNION SELECT 'K' UNION SELECT 'L' UNION SELECT 'M' UNION SELECT 'N' UNION
SELECT 'O' UNION SELECT 'P' UNION SELECT 'Q' UNION SELECT 'R' UNION SELECT 'S' UNION SELECT 'T' UNION
SELECT 'U' UNION SELECT 'V' UNION SELECT 'W' UNION SELECT 'X' UNION SELECT 'Y' UNION SELECT 'Z'
), Permutations AS (
SELECT SecondChar.[Character] + FirstChar.[Character] AS PermuteID
FROM Ranks AS FirstChar
CROSS JOIN Ranks AS SecondChar
), PermutationsKeyed AS (
SELECT ROW_NUMBER() OVER (ORDER BY PermuteID ASC) AS PrimaryKeyHolder,
PermuteID
FROM Permutations
), MaxPK AS (
SELECT MAX(Perm.PrimaryKeyHolder) + 1 AS MaxPK
FROM #ExistingTable AS E
INNER JOIN PermutationsKeyed AS Perm ON (E.ID = Perm.PermuteID)
)
SELECT #NewID = Perm.PermuteID
FROM PermutationsKeyed AS Perm
INNER JOIN MaxPK AS M ON (Perm.PrimaryKeyHolder = M.MaxPK)
SELECT #NewID
I'm not sure how you wanted to go about returning the next value but I think this a simple and efficient ways to get all your values. Let me know if you need anything else.
DECLARE #values TABLE (val CHAR(1));
DECLARE #int INT = 48,
#letters INT = 65;
IF OBJECT_ID('dbo.tbl_keys') IS NOT NULL
DROP TABLE dbo.tbl_keys;
--This will hold the values so you can always reference them
CREATE TABLE dbo.tbl_Keys
(
--Primary key will create a clustered index on rank_id by default
rank_id INT PRIMARY KEY,
ID_Code CHAR(2)
);
--Another index on ID_Code
CREATE NONCLUSTERED INDEX idx_ID_Code ON tbl_keys(ID_Code);
--This is how I get all your individual values
WHILE (SELECT COUNT(*) FROM #values) < 36
BEGIN
IF(#int <= 57)
INSERT INTO #values VALUES(CHAR(#int));
INSERT INTO #values
VALUES (CHAR(#letters))
SET #int = #int + 1;
SET #letters = #letters + 1;
END
--Insert all possible combinations and rank them
INSERT INTO tbl_Keys
--ASCII is your best friend. It returns the ASCII code(numeric value) for characters
SELECT ROW_NUMBER() OVER (ORDER BY ASCII(A.val),ASCII(B.val)) AS rank_id,
A.val + B.val ID
FROM #values A
CROSS JOIN #values B;
I provide two different ways of getting the next ID_code(Read comments):
--Here's some dummy data
WITH CTE_DummyTable
AS
(
SELECT '00' ID_Code
UNION ALL
SELECT '01'
UNION ALL
SELECT '02'
)
----Here's how to get the next value with the assumption there are no gaps in your data
--SELECT MIN(ID_Code) next_id_code
--FROM tbl_Keys
--WHERE ID_code > (SELECT MAX(id_code) FROM CTE_DummyTable)
--This one doesn't assume the gaps and returns the lowest available ID_code
SELECT MIN(ID_Code) next_id_code
FROM tbl_Keys
WHERE ID_code NOT IN (SELECT DISTINCT id_code FROM CTE_DummyTable)
Note: If you were ever to want to convert your alphanumeric values really easily for whatever reason without changing the rank try this.
SELECT rank_id,
ID_code,
CAST(CONCAT(ASCII(LEFT(id_code,1)),ASCII(RIGHT(id_code,1))) AS INT) AS numeric_id_code
FROM tbl_Keys

create a list of the alphabet via SQL

I would like to produce results from the alphabet via SQL?
Something like this:
A
B
C
D
E
F
I have tried:
SELECT
'A','B','C'
But this just produces the letters across in columns.
Use table spt_values and convert values to chars
SELECT Char(number+65)
FROM master.dbo.spt_values
WHERE name IS NULL AND
number < 26
EDIT: This table is undocumented. But, it's used by many system storedprocedures and it's extremely unlikely for this table to disappear, since all those procs should be rewritten. This would be like poking a sleeping lion.
--
-- tally = 9466 rows in my db, select upper & lower alphas
--
;
with
cte_tally as
(
select row_number() over (order by (select 1)) as n
from sys.all_columns
)
select
char(n) as alpha
from
cte_tally
where
(n > 64 and n < 91) or
(n > 96 and n < 123);
go
The sys.all_columns is a documented table. It will be around for a while.
http://technet.microsoft.com/en-us/library/ms177522.aspx
It seems clear that the table, sp_values, is undocumented and can be removed in the future without any comment from Microsoft.
Try:
select 'A' union
select 'B' union
select 'C'
If you want to print from A to Z, then:
DECLARE #i int=65
WHILE #i < 91
BEGIN
PRINT CHAR(#i);
SET #i=#i+1;
END
You could use U-SQL
Select
[letter]
From
(
Values
('A')
,('B')
,('C')
) As [Letters]([letter])
with AlphabetList as
(
select char(65) letter
union all
select char(ascii(letter) + 1)
from AlphabetList
where letter <> 'Z'
)
select *
from AlphabetList
Using a recursive CTE (common table expression) to output the alphabet, A-Z, one row per letter/character:
;WITH cteAZ AS
(
SELECT ASCII('A') [AlphaCode],CAST('A' AS CHAR(1)) [Alpha]
UNION ALL
SELECT a.AlphaCode + 1 [AlphaCode],CAST(CHAR(a.AlphaCode + 1) AS CHAR(1)) [Alpha]
FROM cteAZ a WHERE a.AlphaCode < ASCII('Z')
)
SELECT
az.AlphaCode,az.Alpha
FROM
cteAZ az
Try this
;WITH CHARA2Z
AS (
SELECT
[ASCII] = ASCII('A'),
[LETTER] = CHAR(ASCII('A'))
UNION ALL
SELECT
[ASCII] + 1,
[LETTER] = CHAR([ASCII]+1)
FROM
CHARA2Z
WHERE
[ASCII] < ASCII('Z')
)
SELECT * FROM CHARA2Z
Replace 'A' & 'Z' by 'a' & 'z' for small letters.
Stemming from #MarkoJuvančič's answer, but a solution that will work on every SQL DBMS:
CREATE TEMPORARY TABLE alphabet (ltr CHAR(1));
SET #row_number = 0;
INSERT INTO alphabet
SELECT
CHAR((#row_number:=#row_number + 1) +64) -- 'A' is the 65th character on the ASCII table
FROM customer -- any table with 26 or more rows could suffice for this job
WHERE #row_number < 26;
SELECT 'A' letter
UNION ALL
SELECT 'B' letter
UNION ALL
SELECT 'C' letter
UNION ALL
SELECT 'D' letter
UNION ALL
SELECT 'E' letter
UNION ALL
SELECT 'F' letter
UNION ALL
SELECT 'G' letter
UNION ALL
SELECT 'H' letter
UNION ALL
SELECT 'I' letter
UNION ALL
SELECT 'J' letter
UNION ALL
SELECT 'K' letter
UNION ALL
SELECT 'L' letter
UNION ALL
SELECT 'M' letter
UNION ALL
SELECT 'N' letter
UNION ALL
SELECT 'O' letter
UNION ALL
SELECT 'P' letter
UNION ALL
SELECT 'Q' letter
UNION ALL
SELECT 'R' letter
UNION ALL
SELECT 'S' letter
UNION ALL
SELECT 'T' letter
UNION ALL
SELECT 'U' letter
UNION ALL
SELECT 'V' letter
UNION ALL
SELECT 'W' letter
UNION ALL
SELECT 'X' letter
UNION ALL
SELECT 'Y' letter
UNION ALL
SELECT 'Z' letter;