SQL String Manipulation and character replacement - sql

I have a database with a list of old ItemID's that need updating to a new format.
The old format is of the form 8046Y and the new format moves the 4th digit to the end and prepends a hyphen and adds a 0 if it's a single digit. The old format also uses alpha characters when the number goes over 9 for example 464HB where the H represents 17. I also need to add a 1 to the beginning of the new format. All this can be done with string manipulation in SQL I hope.
Some examples:
8046Y becomes 1804Y-06
464HB becomes 1464B-17 (H = 17)
Can anyone give me some pointers as to how to go about this in SQL?
I got as far as:
select '1' + LEFT(ItemID, 3) + RIGHT(ItemID,1) + '-' + '0' + SUBSTRING(ItemID,3,1) from items
But the conversion from a=10 to z=36 stumped me

Try this:
select
'1'
+ left(#str,3)
+ right(#str,1)
+ '-'
+ case
when substring(#str,4,1) like '%[0-9]%' 1 then right('00' + substring(#str,4,1),2)
else cast(10 + ascii(substring(#str,4,1))-ascii('A') as varchar(2))
end
Explanation: If the 4th character is a digit, then do not change the value and append it after padding with a zero. Otherwise, use ASCII to get the ASCII value for that character, get it's difference with the value for 'A' and add the offset of 10.
Demo

Since I don't know if there are any other special character to consider except 'H' only included this single character.
DECLARE #val CHAR(5) = '464HB'
SELECT #val, '1' + LEFT(#val,3)+SUBSTRING(#val,5,1)+'-'+CASE WHEN +SUBSTRING(#val,4,1)='H' THEN '17' ELSE '0'+SUBSTRING(#val,4,1) END

select '1' + LEFT(ItemID, 3) + RIGHT(ItemID,1) + '-'
+CASE RIGHT(LEFT(ItemID,1),2)
WHEN 'a' then 10
WHEN 'b' THEN 11
etc...
END [NewItemID]
from items
Just add the appropriate cases in that format.

I do it only for the challenge, i dont recommend to use
DECLARE #id varchar(5) = '8046Y'
--SET #id = '464HB'
SELECT
'1' +
LEFT(#id, 3) +
RIGHT(#id, 1) +
'-' +
CASE WHEN ISNUMERIC(RIGHT(LEFT(#id, 4), 1)) = 1 THEN
RIGHT(LEFT(#id, 4), 1)
ELSE
RIGHT('00' + CONVERT(VARCHAR, ASCII(RIGHT(LEFT(#id, 4), 1)) - 64 + 9), 2)
END
-64 for the Start of ASCII A and +9 for your convention

Personally, I'd create a function for it.
Create a variable to handle the new value.
Manipulate the positions through SUBSTRING, you can also use RIGHT or LEFT
When adding zeros in single digit numbers, just do conditional statement
Regarding the conversion of letters to numbers(e.g. letter H), the converted value of the first letter is 65 assuming it's all capital. So, A=65, B=66, H=72 and so on. Use this data in manipulating the values. Uhm, I'll give you my thoughts but you can optimize it (since I don't have lots of time).
Taking your example of H=17, so A=10. Just subtract 55 in the conversions. So H=72(-55) becomes 17. This is applicable to all letters (in uppercase only).
I think this much is more than enough to guide you. Hope this would help.

Related

CAST(somenumber as VARCHAR(10)) + somestring returns Error converting data type varchar to numeric

I'm trying to combine a min and max salary with a hyphen for display in a report. I feel like I've done this a hundred times but I still can't figure out why I'm getting the "Error converting data type varchar to numeric" especially since I'm trying to convert a numeric to varchar not the other way around.
amt_exp_formatted = CASE
WHEN a.class_code IN ('9997','9998','9999') THEN 0
--ELSE CAST(e.min_sal as VARCHAR(10)) + '-' + CAST(e.max_sal as VARCHAR(10))
ELSE CONVERT(VARCHAR(1), 1) + CONVERT(VARCHAR(1), 'a')
END
In the above example if I use 'a' I get the error. If I change 'a' to '9' then it works AND it appends 9 to the 1 (i.e. 19) rather than adding them together which is exactly what I want but with a character string. I've tried both CAST and CONVERT with no luck. I know I shouldn't need the second CONVERT on the letter 'a' but I was just trying to force the data types to be the same just in case. I have no doubt at all I'm missing something simple but I can't seem to get it so I figured it wouldn't hurt to ask the community.
Thank you!
A case expression returns one value with a determinate type. If any returned fork returns a number, then number it is. And strings get converted.
So, be sure you are returning a string in all cases:
(CASE WHEN a.class_code IN ('9997', '9998', '9999')
THEN '0'
ELSE CONCAT(e.min_sal, '-', e.max_sal)
END)
CONCAT() automatically converts the arguments to strings.
This is becuase you are mixing the data type. in the first part of case you were returning 0 while in the else part you're converting it to varchar(). - you can try the below returning 0 as also varchar
amt_exp_formatted = CASE
WHEN a.class_code IN ('9997','9998','9999') THEN '0'
--ELSE CAST(e.min_sal as VARCHAR(10)) + '-' + CAST(e.max_sal as VARCHAR(10))
ELSE CONVERT(VARCHAR(1), 1) + CONVERT(VARCHAR(1), 'a')
END

Does the SQL CASE statement treat variables differently from columns?

I have the following code in a stored procedure and am trying to conditionally format a calculated number based on its length (if the number is less than 4 digits, pad with leading zeros). However, my case statement is not working. The "formattedNumber2" result is the one I'm looking for.
I'm assuming the case statement treats the variable strangely, but I also don't know of a way around this.
DECLARE #Number int = 5
SELECT
CASE
WHEN (LEN(CONVERT(VARCHAR, #Number)) > 4)
THEN #Number
ELSE RIGHT('0000' + CAST(#Number AS VARCHAR(4)), 4)
END AS formattedNumber,
LEN(CONVERT(VARCHAR, #Number)) AS numberLength,
RIGHT('0000' + CAST(#Number AS VARCHAR(4)), 4) AS formattedNumber2
I get the following results when I run the query:
formattedNumber numberLength formattedNumber2
-------------------------------------------------
5 1 0005
SQL DEMO
The problem is you are using different data type on your case , integer and string. So the CASE stay with the first type he find and convert the rest.
CASE WHEN (LEN(convert(VARCHAR, #Number)) > 4) THEN convert(VARCHAR, #Number)
This can be done a lot easier with format() since version 2012.
format(n,
'0000')
And that would also handle negative values, which your current approach apparently doesn't.
Prior 2012 it can be handled with basically replicate() and + (string concatenation).
isnull(replicate('-',
-sign(n)), '')
+
isnull(replicate('0',
4
-
len(cast(abs(n) AS varchar(10)))
),
'')
+
cast(abs(n) AS varchar(10))
(It targets integer values, choose a larger length for the varchar casts for bigint.)
db<>fiddle

Conversion failed from VARCHAR to INT

I am trying to use SQL to get new policy number based on the existing one. I don't want to use update since I don't want to permanently change the records.
My policy numbers are like PFA991228-01 and I want to use SQL to modify and get PFA991228-02. So I am just updating the last 2 digits from 00 to 01 or from 05 to 06 etc. Right now I am getting error for converting varchar to int.
I am new to SQL so not sure if I can just achieve it in my first select statement instead of using sub-query
select
left(p.policynum, 9)
+ '-'
+ right('00' + convert(varchar(255), right(p.policynum, 2) + 1), 2) as newPolicy
From Company55.dbo.policy p
where p.policynum not like '%S%'
I would suggest this logic:
select (left(p.policynum, 9) + '-' +
right( '00' + try_convert(int, right(p.policynum, 2)) + 1 as varchar(255)), 2) as newPolicy
From Company55.dbo.policy P
where p.policynum not like '%S%' and
p.policynum like '%[0-9][0-9]';
Notes:
The where ensures that the output rows all end in two digits.
The try_convert() ensures that the conversion to integer succeeds -- the where is not enough.
This works for both 1- and 2- digit suffixes.
I see no reason for the subquery. right(p.policynum, 2) isn't really that much more complicated than term, for instance.

SQL Statement Meaning

Can someone tell me what this SQL statement is doing? Break it down as to what each part of the statement is doing.
convert(char(11),(field name 1 + right('0' + cast(field name 2 as varchar(2),2))
convert(char(11),(field_name_1 + right('0' + cast(field_name_2 as varchar(2),2))
convert() (documentation https://technet.microsoft.com/en-us/library/ms187928(v=sql.105).aspx):
Tells the sql server to convert the value in the second parameter to the type given in the first parameter.
char(11):
Tells the sql server that the value behind the command needs to become a character field type, of a maximum length of 11 characters.
after the comma we have the following
(field_name_1 + right('0' + cast(field_name_2 as varchar(2),2)
field_name_1 corresponds to the field on the table you're reading. It will get the value of that field and put it there.
+ means append string. Append the value that follows after the + to the value before the +
for example
'foo' + 'bar' = 'foobar'
'foo' + 'baz = 'foobaz'
So in this case whatever follows behind the + should be appended tot he value of field_name_1
right is a function, get N characters starting from the end of the string(documentation https://learn.microsoft.com/en-us/sql/t-sql/functions/right-transact-sql)
within this function a lot happens. But the first part before the comma '0' + cast(field_name_2 as varchar(2) is the string right is called upon, and the 2 is the number of characters to select from it, starting from the end.
So if you have the following values fed into right
013
03
044
you'll end up with
13
03
44
Now we have this part:
'0' + cast(field_name_2 as varchar(2)`
'0' is a string literal. This is just a string, of length one, that contains the character 0
+ means append string. Append the value that follows after the + to the value before the +
So in this case, anything that follows the + will be appended to 0.
example:
'0' + 'foo' = '0foo'
'0' + '1' = '01'
cast(field_name_2 as varchar(2))
In your code you're actually missing a closing ) here, might cause you some trouble.
Basically what it does it takes the value of field_name_2 which is probably of the type integer(just guessing) and converts it to the type of varchar, with a maximum length of 2(guessing the number will never exceed 99).
so a number with value of 1 gets turned into a string with the character for the value 1, namely '1'.
2 = '2';
33 = '33';
42 = '42';
this combined with the previous part would yield
'0' + '2' = '02';
'0' + '33' = '033';
'0' + '42' = '042';
that will be fed into the right(value, 2); which will result in
right('02', 2) = '02';
right('033', 2) = '33';
right('042', 2) = '42';
which will be appended to the value of field_name_1
'foobar' + '02' = 'foobar02';
which is then converted in a character type string value of maximum 11 characters long.

Adding leading zeros to result from substring in SQL Server 2008

I have a substring which pulls the data I need but I need to add a leading zero to the front of the result. I've searched and found several samples of pulling data with leading zeros but none using a substring. I can add the zero to the end of the result but do not know how to add it to the front. The substring I am using is shown below.
"substring((substring(convert(char(6),Convert(int,a.nor_ppd_hrs_no*100) + 100000),3,4) + space(16)),1,16) as 'ApprovedHrs',"
This produces a result like this 7500 and I need it to look like this 07500.
Thanks
One of most simple solution for adding leading zeros in order to get a number with a desired width (ex. 16 digits) is to concatenate a string of zeros (REPLICATE('0', 15) or '000000000000000') with the source number (ex. 123) converted to VARCHAR ('123'). Then, the result '000000000000000123' is truncated to desired length (ex. 16 digits) using the RIGHT function:
DECLARE #Num INT;
SET #Num = 123;
SELECT RIGHT(REPLICATE('0', 15) + CONVERT(VARCHAR(11), #Num), 16) AS NumWithLeadingZeros1
SELECT RIGHT('000000000000000' + CONVERT(VARCHAR(11), #Num), 16) AS NumWithLeadingZeros2
Output:
NumWithLeadingZeros1
--------------------
0000000000000123
NumWithLeadingZeros2
--------------------
0000000000000123
Assuming you need the resulting string to be 5 characters length,
stuff(substring((substring(convert(char(6),Convert(int,a.nor_ppd_hrs_no*100) + 100000),3,4) + space(16)),1,16), 1, 0, replicate('0', 5 - len(substring((substring(convert(char(6),Convert(int,a.nor_ppd_hrs_no*100) + 100000),3,4) + space(16)),1,16)))) as 'ApprovedHrs
Use the STR() function to convert a number to a fixed-length, right-justified string. By default, it pads with spaces, so replace ' ' with '0' to get a zero-padded output.
SELECT REPLACE(STR(a.nor_ppd_hrs_no*100,5),' ','0') FROM MyTable