How to update the first digit of a number only? - sql

I need to update the first digit of numbers.
For example, 3003.
I only want the first '3' to be changed to '2' and don't want the last digit '3' to be changed.
Something like the following faulty query:
update table
set defaulttopicorder = replace(defaulttopicorder, left(defaulttopicorder,1), 2)
where ....

Assuming the defaulttopicorder column is a non-decimal, this will add 1 to the first digit of the number:
SET defaulttopicorder = defaulttopicorder + POWER(10, LEN(STR(defaulttopicorder)))
...so if you want to subtract 1 from the first digit:
SET defaulttopicorder = defaulttopicorder + -1 * POWER(10, LEN(STR(defaulttopicorder)))

Use STR(defaulttopicorder) to make a string out of the number, SUBSTRING around to take the part of it starting at index 2, + to concatenate the leading '2' with that substring.

This sounds like homework, so rather than giving the answer, how about a suggestion.
You can turn the number into a string, then just modify the first character in the varchar, but, when you increase it, remember that it may be incremented if you go from 9 to 10.
Another approach is to someone remove all the other digits, so if you have value:
3976, then have it be 3000, and increment then add back what you had removed.

Here's a quick inelegant approach:
DECLARE #MyInt INT = 5003
PRINT CAST(SUBSTRING(CAST(#MyInt AS VARCHAR(4)), 1, 1) + 1 AS CHAR(1)) + SUBSTRING(CAST(#MyInt AS VARCHAR(4)), 2, LEN(#MyInt) - 1)
Convert to an update as required. Tested on SQL08.

Here's a slightly different approach, which doesn't involve turning it into a string (so it may be more efficient, although you'd have to test it to be certain).
If you have a number N, then log10(N) is the power that 10 would have to be raised to in order to get N.
But if you round it down and raise 10 to that power (i.e. 10floor(log10(N))) you'll get the place value of the leftmost digit.
Now, multiply that place value by the amount you want to add or subtract from the digit (e.g. -1 or 1) and add the result to the original number.
So, given your example:
N = 3003
log10(N) = approx. 3.477
floor(3.477) = 3
103 = 1000
So, if you want to add 1 to the first digit, add 1 * 1000 (=1000) to the number; if you want to subtract 1, add -1 * 1000 (=-1000) to the number.
Of course, you'll want to be careful of rounding errors, which can pop up unexpectedly due to problems with representing decimal values as binary.

Related

Always include right most 6 digits, but allow for more digits if they aren't leading zeroes?

This may sound like a weird request, but I have to make an excel sheet with EXACTLY the same format as their old sheet. The values in the column in question will be a numeric code. I need to display up to 8 digits, and no less than 6 digits. The code will only be 7 or 8 digits if the first number in the sequence is not zero. If there are 6 digits or less, I need to display 6 digits including leading zeroes. Here is an example:
The data comes in like this:
000023547612
000000873901
000031765429
000000000941
000000055701
I need those numbers to display as:
23547612
873901
31765429
000941
055701
Is there a way to achieve this in a SQL statement?
You can check the length of the string and use right to pad it. But GSerg's answer is better.
declare #Test table (Number varchar(12))
insert into #Test (Number)
values ('000023547612'),('000000873901'),('000031765429'),('000000000941'),('000000055701')
select Number
, case when len(convert(varchar(12), convert(int, Number))) <= 6 then right('000000'+convert(varchar(12), convert(int, Number)),6) else convert(varchar(12), convert(int, Number)) end
, format(convert(int, Number), N'##000000') -- GSerg's Answer
from #Test
Returns:
Number Attempt1 Attempt2 (GSerg)
000023547612 23547612 23547612
000000873901 873901 873901
000031765429 31765429 31765429
000000000941 000941 000941
000000055701 055701 055701
PS: In future if you provide test data in this format (table variable or temp table) you will make it much easier for people to answer.
You can use
SELECT Substring('0078956', Patindex('%[^0 ]%', '0078956' + ' '), Len('0078956') ) AS Trimmed_Leading_0;

how to repeat characters in a string

I'm trying to link two tables, one has an 'EntityRef' that's made of four alpha characters and a sequential number...
EntityRef
=========
SWIT1
LIVE32
KIRB48
MEHM38
BRAD192
The table that I'm trying to link to stores the reference in a 15 character field where the 4 alphas are at the start and the numbers are at the end but with zeros in between to make up the 15 characters...
EntityRef
=========
SWIT00000000001
LIVE00000000032
So, to get theses to link, my options are to either remove the zeros on one field or add the zeros on the other.
I've gone for the later as it seems to be a simpler approach and eliminates the risk of getting into problems if the numeric element contains a zero.
So, the alpha is always 4 characters at the beginning and the number is the remainder and 15 minus the LEN() of the EntityRef is the number of zeros that I need to insert...
left(entityref,4) as 'Alpha',
right(entityref,len(EntityRef)-4) as 'Numeric',
15-len(EntityRef) as 'No.of Zeros'
Alpha Numeric No.of Zeros
===== ======= ===========
SWIT 1 10
LIVE 32 9
KIRB 48 9
MEHM 38 9
MALL 36 9
So, I need to concatenate the three elements but I don't know how to create the string of zeros to the specified length...how do I do that??
Concat(Alpha, '0'*[No. of Zeros], Numeric)
What is the correct way to repeat a character a specified number of times?
You can use string manipulation. In this case:
LEFT() to get the alpha portion.
REPLICATE() to get the zeros.
STUFF() to get the number.
The query:
select left(val, 4) + replicate('0', 15 - len(val)) + stuff(val, 1, 4, '')
from (values ('SWIT1'), ('ABC12345')) v(val)
You may try left padding with zeroes:
SELECT
LEFT(EntityRef, 4) +
RIGHT('00000000000' + SUBSTRING(ISNULL(EntityRef,''), 5, 30), 11) AS EntityRef
FROM yourTable;
Demo
With casting to integer the numeric part:
select *
from t1 inner join t2
on concat(left(t2.EntityRef, 4), cast(right(t2.EntityRef, 11) as bigint)) = t1.EntityRef
See the demo.
I found the answer as soon as I posted the question (sometimes it helps you think it through!).
(left(entityref,4) + replicate('0',15-len(EntityRef)) +
right(entityref,len(EntityRef)-4)),

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

Max of a part of split string

I have, in my DB oracle 10g, a field that contains references.
It's stored as : name/yyyy/mm/number
The new number, is the max number found in the part mm/number.
So, for now, I have a split of my string that gives me a list of str_array like this :
str_array(name, yyyy, mm, number)
I'd like, with this, found max number, for the couple mm/number.
Is this possible to do this?
Can I have something like :
SELECT MAX(split(reference, '/').lastPartOfArray) into nb
FROM table
where lastPartOfArray-1 = sysdate.month;
Data samples :
Smith/2013/12/1
Smith/2013/11/1
Smith/2013/12/3
Jones/2013/12/6
Smith/2013/12/3
Jones/2013/11/7
Since we are in the month 12, a max on those data must give me 6 into nb.
The number part, has no limit, it can be 1000, 10000...
The part Jones/2013 doesn't really matter for the number. But I can't have the same number, for a month.
My apologies, I don't know if this is possible, so I tried to write what I want in the query.
Is this possible, or should I create more than one field in my table(name/yyyy, mm, number)?
edit : valex answer and some custom
select MAX(CAST(SUBSTR(num,INSTR(num,'/')+9,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
So this, count searching first occurence.
select MAX(CAST(SUBSTR(num,INSTR(num,'/',1 ,n)+1,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
This found the n occurence of the char.
This is a helpful solution in other cases.
To get a maximum you should convert this last part into INT values otherwise you can get not right results because of STRING comparing rules will be used.
As soon as /YYYY/MM/ has got a fixed length = 9 so we can find first \ position and add 9 to this position to find a last part number substring start.
Here is an example:
select MAX(CAST(SUBSTR(num,INSTR(num,'/')+9,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
SQLFiddle demo
Also you can exclude wrong formatted values from this query to avoid conversion errors using the following way:
select MAX(CAST(SUBSTR(num,INSTR(num,'/')+9,1000) as Int))
from T
where num like TO_CHAR(sysdate,'%/YYYY/MM/%')
AND
LENGTH(TRIM(TRANSLATE(SUBSTR(num,INSTR(num,'/')+9,1000),
' 0123456789', ' '))) is null
SQLfiddle demo
Try this:
SELECT
MAX(SUBSTR(num, INSTR(num, '/', 1, 3) + 1))
FROM ref
WHERE
SUBSTR(num, INSTR(num, '/', 1, 2) + 1, INSTR(num, '/', 1, 3) - INSTR(num, '/', 1, 2) - 1) = TO_CHAR(sysdate, 'MM')
Sample: http://sqlfiddle.com/#!4/1b03a/1

Pad a number with zeros, but only if it's below a certain length?

I have numbers that must be at least 7 digits long. For example:
0000001
123456789
0012345
Are all valid. I only need to pad the number with 0's only if its length is below 7. How do I do this in SQL Server? The best I've been able to get is to pad the number if the length is less than 7, but above that, it starts to truncate the number instead.
SELECT CASE WHEN LEN(CONVERT(VARCHAR(12), column)) > 7 THEN
CONVERT(VARCHAR(12),column) ELSE
RIGHT('0000000' + CONVERT(VARCHAR(12), column), 7) END
FROM dbo.table;
Aaron Bertrand beat me to it.
I'd like to add that it might also be useful to encapsulate both the character and number of times you have to repeat it, so that if it needs to change sometime in the future, it's easy to do it. You can do this using REPLICATE. So expanding on Aaron's example:
DECLARE #num_digits as int = 7
SELECT RIGHT(REPLICATE('0', #num_digits) + col, #num_digits) FROM dbo.table;
Hi check this out.
declare #num table(num varchar(10))
insert into #num
VALUES('0000001'),('123456789'),('0012345'),('123'),('11')
select CASE when len(num) < 7 then REPLICATE('0',(7-len(num)))+num else num END from #num