Netezza convert char to numeric - arithmetic - and convert again to char - sql

I have a field PersonNumb which is varchar(30) and needs to get converted to numeric, than do some arithmetic(in this case some simple addition Value + 10, just for example) and than convert this field again to varchar.
I do cut off the '|' to convert the field to number, without blanks or other characters, everything fine.
to_number(translate(PersonNumb,'|',''),999999999999999999999999999999) AS NewPersonNumb;
Than i do the arithmetic with
update XX..YY set NewPersonNumb = NewPersonNumb + 10;
But the last step wont work, the field is still numeric and not varchar.
update XX..YY set NewPersonNumb = to_char(NewPersonNumb,'999999999999999999999999999999');
Put the whole statement in one row doesnt work too...
update XX..YY set NewPersonNumb = to_char(NewPersonNumb + 10,'99999999999999999999999999');

I have done the following its working for me .
TEST.ADMIN(ADMIN)=> create table YY (PersonNumb varchar(30)) distribute on random;
CREATE TABLE
TEST.ADMIN(ADMIN)=> insert into YY values('22222222|111111|4');
INSERT 0 1
TEST.ADMIN(ADMIN)=> update yy set PersonNumb = to_number(translate(PersonNumb,'|',''),999999999999999999999999999999)+10 ;
UPDATE 1
TEST.ADMIN(ADMIN)=> select * from YY;
PERSONNUMB
-----------------
222222221111124

Perhaps someone will need it
Put everything in the select
(to_number(translate(PersonNumb,'|',''),99999999999999999999999999999) + 10)::varchar(30) AS NewPersonNumb

Related

How can we read a varchar column, take the integer part out and add new column incrementing that integer part using script

I need to write a SCRIPT for below scenario:
We have a column X with rows value for this column X as X01,X02,X03,X04........
The problem I am stuck with is that I needed to add another row to this table based on the value of the last row that is X04, Well I am able to identify the logic that I need to work which is given below:
I need to read value X04
Take the integer part 04
Increment by 1 => 05
Save column value as X05
I am able to pass with the 1st step which is not very hard. The problem that I am facing is the next steps. I have researched and tried quite a lot commands but none worked.
Any help is highly appreciated. Thanks.
You seem to be describing:
select concat(left(max(x), 1),
right(concat('00', try_convert(int, right(max(x), 2)) + 1), 2)
from t;
This is doing the following:
Taking the left most character.
Converting the two right characters to a number and adding one.
Converting that back to a zero-padded string.
Here is a db<>fiddle.
Now: That you want to increment a string value seems broken. You should just use an identity column or sequence to assign a number. You can format the value as a string when you query the table -- or use a computed column to store that.
Try below Script
CREATE TABLE #table (x varchar(20))
INSERT INTO #table VALUES('X01'),('X02'),('X03'),('X04')
DECLARE #maxno NVARCHAR(20)
DECLARE #maxstring NVARCHAR(20)
DECLARE #finalno NVARCHAR(20)
DECLARE #loopminno INT =1 -- you can change based on the requirement
DECLARE #loopmaxno INT =10 -- how many number we want to increment
WHILE #loopminno < #loopmaxno
BEGIN
select #maxno = MAX(CAST(SUBSTRING(x, PATINDEX('%[0-9]%', x), 100) as INT))
, #maxstring = MAX(SUBSTRING(x, 1, PATINDEX('%[0-9]%',x)-1))
from #table
where PATINDEX('%[1-9]%',x)>0
SELECT #finalno = #maxstring + CASE WHEN CAST(#maxno AS INT)<9 THEN '0' ELSE '' END + CAST(#maxno+1 AS VARCHAR(20))
INSERT INTO #table
SELECT #finalno
SET #loopminno = #loopminno+1
END

Need to pad zeros left and right for a string value according to decimal format

So if I have a data (varchar) like say 10.1
I need the value as 0000101000000.
means (000010) whole number and (1000000) decimal value.
Its a 13 character string ,numbers coming before decimal point should be in first 6 characters and numbers coming after decimal point should be in last 7 characters
Maybe..?
DECLARE #d decimal(13,7) = 10.1;
SELECT RIGHT('0000000000000' + CONVERT(varchar(13),CONVERT(bigint,(#d * 10000000))),13);
Using my crystal ball here though.
Edit: As, for some reason, the OP is storing a decimal as a varchar (this is a really bad bad idea on it's own), I have added further logic to attempt to convert the value to a decimal first.
As experience has taught many of us, give a user a non-numeric column to store a numeric value in and they're more than happily store a non-numeric value in it, so i have used TRY_CONVERT and assumed you are using SQL Server 2012+:
DECLARE #d varchar(13) = 10.1;
SELECT RIGHT('0000000000000' + CONVERT(varchar(13),CONVERT(bigint,(TRY_CONVERT(decimal(13,7),#d) * 10000000))),13);
SELECT REPLICATE('0',6-LEN(SUBSTRING(CAST([data] AS VARCHAR), 1,
CHARINDEX('.',CAST([data] AS VARCHAR)) -1)))+SUBSTRING(CAST([data] AS VARCHAR), 1,
CHARINDEX('.',CAST([data] AS VARCHAR)) -1)+
SUBSTRING(CAST([data] AS VARCHAR), CHARINDEX('.',CAST([data] AS VARCHAR)) + 1,
LEN(CAST([data] AS VARCHAR)))+REPLICATE('0',7-LEN(SUBSTRING(CAST([data] AS VARCHAR), CHARINDEX('.',CAST([data] AS VARCHAR)) + 1,
LEN(CAST([data] AS VARCHAR))))) AS Whole
FROM Table1
Output
Whole
0000101000000
Demo
http://sqlfiddle.com/#!18/8649d/16
You can use some math and string operations to do it like below
see live demo
declare #var decimal(10,4)
set #var=10.1
select #var,
right(cast(cast(( floor(#var)+ power(10,7)) as int) as varchar(13)),6)
+
cast(cast(((#var- floor(#var)) * power(10,7)) as int) as varchar(13))
There's a fair amount of string manipulation to be done here. I'll step through what I did.
I used a variable for the base number so I could verify different results:
declare #n decimal(9,3) = 10.1
You need 6 spaces left of the decimal and 7 spaces to the right, so I'm doing all the manipulation on a VARCHAR(13). I didn't create a new variable as a VARCHAR because I'm assuming you want to be able to do this conversion in line on the fly, so I'm using that CAST over and over again.
Start by finding the decimal place.
SELECT CHARINDEX('.',CAST(#n as VARCHAR(13)))
In the sample number, that's a 3, but it could obviously change.
Now, get the portion of the number to the left of the decimal place.
SELECT SUBSTRING(CAST(#n as VARCHAR(13)),1,CHARINDEX('.',CAST(#n as VARCHAR(13)))-1)
Then get the portion to the right of the decimal.
SELECT SUBSTRING(CAST(#n as VARCHAR(13)),CHARINDEX('.',CAST(#n as VARCHAR(13)))+1,LEN(CAST(#n as VARCHAR(13))))
Pad the leading zeroes. Put 6 on, concatenate, and take a RIGHT 6. Accounts for no digits to the left of the decimal.
SELECT RIGHT(REPLICATE(0,6) + SUBSTRING(CAST(#n as VARCHAR(13)),1,CHARINDEX('.',CAST(#n as VARCHAR(13)))-1), 6)
Pad the trailing zeroes. Same idea, but in the other direction.
SELECT LEFT(SUBSTRING(CAST(#n as VARCHAR(13)),CHARINDEX('.',CAST(#n as VARCHAR(13)))+1,LEN(CAST(#n as VARCHAR(13)))) + REPLICATE(0,7),7)
Then put it all together.
SELECT RIGHT(REPLICATE(0,6) + SUBSTRING(CAST(#n as VARCHAR(13)),1,CHARINDEX('.',CAST(#n as VARCHAR(13)))-1), 6)
+
LEFT(SUBSTRING(CAST(#n as VARCHAR(13)),CHARINDEX('.',CAST(#n as VARCHAR(13)))+1,LEN(CAST(#n as VARCHAR(13)))) + REPLICATE(0,7),7)
Results.
0000101000000
declare #var varchar(20) = '10000.112'
SELECT FORMAT (FLOOR(#var), '000000') + left((PARSENAME(#var,1)) + replicate('0',7),7)

Procedure to apply formatting to all rows in a table

I had a SQL procedure that increments through each row and and pads some trailing zeros on values depending on the length of the value after a decimal point. Trying to carry this over to a PSQL environment I realized there was a lot of syntax differences between SQL and PSQL. I managed to make the conversion over time but I am still getting a syntax error and cant figure out why. Can someone help me figure out why this wont run? I am currently running it in PGadmin if that makes any difference.
DO $$
DECLARE
counter integer;
before decimal;
after decimal;
BEGIN
counter := 1;
WHILE counter <> 2 LOOP
before = (select code from table where ID = counter);
after = (SELECT SUBSTRING(code, CHARINDEX('.', code) + 1, LEN(code)) as Afterward from table where ID = counter);
IF before = after
THEN
update table set code = before + '.0000' where ID = counter;
ELSE
IF length(after) = 1 THEN
update table set code = before + '000' where ID = counter;
ELSE IF length(after) = 2 THEN
update table set code = before + '00' where ID = counter;
ELSE IF length(after) = 3 THEN
update table set code = before + '0' where ID = counter;
ELSE
select before;
END IF;
END IF;
counter := counter + 1;
END LOOP
END $$;
Some examples of the input/output of the intended result:
Input 55.5 > Output 55.5000
Input 55 > Output 55.0000
Thanks for your help,
Justin
There is no need for a function or even an update on the table to format values when displaying them.
Assuming the values are in fact numbers stored in a decimal or float column, all you need to do is to apply the to_char() function when retrieving them:
select to_char(code, 'FM999999990.0000')
from data;
This will output 55.5000 or 55.0000
The drawback of the to_char() function is that you need to anticipate the maximum number of digits of that can occur. If you have not enough 9 in the format mask, the output will be something like #.###. But as too many digits in the format mask don't hurt, I usually throw a lot into the format mask.
For more information on formatting functions, please see the manual: https://www.postgresql.org/docs/current/static/functions-formatting.html#FUNCTIONS-FORMATTING-NUMERIC-TABLE
If you insist on storing formatted data, you can use to_char() to update the table:
update the_table
set code = to_char(code::numeric, 'FM999999990.0000');
Casting the value to a number will of course fail if there a non-numeric values in the column.
But again: I strong recommend to store numbers as numbers, not as strings.
If you want to compare this to a user input, it's better to convert the user input to a proper number and compare that to the (number) values stored in the database.
The string matching that you are after doesn't actually require a function either. Using substring() with a regex will do that:
update the_table
set code = code || case length(coalesce(substring(code from '\.[0-9]*$'), ''))
when 4 then '0'
when 3 then '00'
when 2 then '000'
when 1 then '0000'
when 0 then '.0000'
else ''
end
where length(coalesce(substring(code from '\.[0-9]*$'), '')) < 5;
substring(code from '\.[0-9]*$') extracts everything the . followed by numbers that is at the end of the string. So for 55.0 it returns .0 for 55.50 it returns .50 if there is no . in the value, then it returns null that's why the coalesce is needed.
The length of that substring tells us how many digits are present. Depending on that we can then append the necessary number of zeros. The case can be shortened so that not all possible length have to be listed (but it's not simpler):
update the_table
set code = code || case length(coalesce(substring(code from '\.[0-9]*$'), ''))
when 0 then '.0000'
else lpad('0', 5- length(coalesce(substring(code from '\.[0-9]*$'), '')), '0')
end
where length(coalesce(substring(code from '\.[0-9]*$'), '')) < 5;
Another option is to use the position of the . inside the string to calculate the number of 0 that need to be added:
update the_table
set code =
code || case
when strpos(code, '.') = 0 then '0000'
else rpad('0', 4 - (length(code) - strpos(code, '.')), '0')
end
where length(code) - strpos(code, '.') < 4;
Regular expressions are quite expensive not using them will make this faster. The above will however only work if there is always at most one . in the value.
But if you can be sure that every value can be cast to a number, the to_char() method with a cast is definitely the most robust one.
To only process rows where the code columns contains correct numbers, you can use a where clause in the SQL statement:
where code ~ '^[0-9]+(\.[0-9][0-9]?)?$'
To change the column type to numeric:
alter table t alter column code type numeric

Converting data for whole table SQL

I'm newbie in SQL and have some questions:
How can I convert columns (in my table with more than 10 000 rows) in my SQL table (I'm using SQL Server 2008):
First column is nvarchar (50) and containing different string values, for e.g. like 20131211142319 and it's a date and time - 2013/12/11 14:23:19. How can I convert this value into date & time and affect this on all rows in this column (more than 10 000).
And also I have column with numbers, all this numbers start from # + number - e.g. #8339274. How can I delete character "#" before all numbers in all rows? Note, that numbers in this column have a different length, from 5 characters to 15 characters.
Thank you in advance.
I couldn't find a more elegant solution for the datetime conversion but here you go:
1. DATETIME conversion
This assumes your value is always in the same format you specified:
Example code for you to run
DECLARE #Value VARCHAR(255) = '20131211142319'
SELECT CONVERT(DATETIME,LEFT(#Value,8) + SPACE(1) + STUFF(STUFF(STUFF(RIGHT(#Value,6), 1, 0, REPLICATE('0', 0)),3,0,':'),6,0,':'))
This splits the field into two sections, the DATE portion LEFT(#Value,8) and then the TIME
STUFF(STUFF(STUFF(RIGHT(#Value,6), 1, 0, REPLICATE('0', 0)),3,0,':'),6,0,':'). The TIME portion is essentially just adding in the colon where applicable (see STUFF on MSDN)so that it returns a value such as:
20131211 14:23:19 This makes it applicable to directly convert to a DATETIME.
2. Removing the # from the numbers
Example code for you to run
DECLARE #ValueNumber VARCHAR(255) = '#8339274'
SELECT SUBSTRING(#ValueNumber,2,LEN(#ValueNumber))
The above statement will take your number and only return data from the 2nd value onwards, excluding the #. See SUBSTRING on MSDN
To make this run on your table, just replace my variable names in the SELECT statement with your column names.
Example using the above on columns in a table:
SELECT CONVERT(DATETIME,LEFT([DATECOLUMNNAME],8) +
SPACE(1) + STUFF(STUFF(STUFF(RIGHT([DATECOLUMNNAME],6),
1, 0,REPLICATE('0',0)),3,0,':'),6,0,':')) AS [Date],
SUBSTRING([NUMBERCOLUMNNAME],2,LEN([NUMBERCOLUMNNAME])) AS [Number]
FROM [TABLENAME]
Replace [DATECOLUMNNAME] with the name of the column that holds your datetime value. Replace the [NUMBERCOLUMNNAME] with the name of the column that holds your number with the #.
Then finally replace [TABLENAME] with your table name that contains those columns.
try this : below answer is also correct
declare #a nvarchar(50)
set #a='20131211142319'
select cast(left(#a,4)+'/'+substring(#a,5,2)+'/'+substring(#a,7,2)+ ' '+ substring(#a,9,2)+':'+substring(#a,11,2)+':' +right(#a,2) as datetime)
output's this --2013-12-11 14:23:19.000
declare #a nvarchar(10)
set #a='#1234567'
select replace(#a,'#','')
outputs this--1234567

Search by numeric Value

Using Sql Server 2005
Table1
ID Value
ABC001
BCE002
...
I have search column, when i search the id like this "001" it is showing empty, when I search "ABC001" then it is showing the values.
Query
Select * from table where id = '" & txtid & "'
txtid = textbox
I want to search only the numeric value in the ID.
How to write a query for the numeric search.
Need Query Help
select * from MyTable
where Value LIKE '[A-Z][A-Z][A-Z]001'
OR
select * from MyTable
where Value LIKE '[A-Z][A-Z][A-Z]' + RIGHT('000' + CONVERT(VARCHAR, #id), 3)
SELECT * FROM Table1 WHERE id LIKE '%001'
The answer given by Mitch Wheat will work if every ID you give is 3 letters in caps followed by a numberical value which has 3 digits.
The answer given by rayman86 essentially disregards anything in the front. It merely looks for anything that ends with 001.
If the length of the ID varies and/or the first few characters are not even letters, it's better to use the code that rayman86 has provided. So just use the SELECT * FROM Table WHERE ID LIKE '%Numbers' where Numbers is your numerical value.
A literal interpretation of the question without making any assumptions:
Create this function
create function dbo.numericonly(#s varchar(max))
returns float as
begin
declare #i int set #i = 1
while #i <= len(#s)
if ascii(substring(#s,#i,1)) between 48 and 57
set #i = #i + 1
else
set #s = stuff(#s,#i,1,'')
return #s
end
GO
Use this query
Select * from table1 where dbo.numericonly(id) = '" & txtid & "'