How to remove just the numeric data to fields - sql

We have data that will be entered into a table, and right now it comes as [68.0,00.2]. I want to lose the [ ] at the front and end, and no comma, put the numeric info into different fields. When I try something like what I have below:
Select SUBSTRING('[68.0,00.2]', 2,CHARINDEX(',','[68.0,00.2]')-2) as cpu_01,
SUBSTRING('[68.0,00.2]', CHARINDEX(',','[68.0,00.2]')+1,
(LEN('[68.0,00.0]')-1)) as cpu_02
I get:
cpu_01 cpu_02
68.0 00.2]
Why can I not get rid of that last ] ??

I don't recommend the method you're using to split a string, but to answer your specific question of why you get the bracket:
The final parameter of SUBSTRING() is length, you're treating it as if it were the ending position.
SUBSTRING ( expression ,start , length )
length Is a positive integer or bigint expression that specifies how
many characters of the expression will be returned. If length is
negative, an error is generated and the statement is terminated. If
the sum of start and length is greater than the number of characters
in expression, the whole value expression beginning at start is
returned.
This would work:
Select SUBSTRING('[68.0,00.2]', 2,CHARINDEX(',','[68.0,00.2]')-2) as cpu_01,
SUBSTRING('[68.0,00.2]', CHARINDEX(',','[68.0,00.2]')+1,
(LEN('[68.0,00.0]')-CHARINDEX(',','[68.0,00.2]'))-1) as cpu_02

I would use apply for this type of operation:
select left(v1.str, charindex(',', v1.str) - 1),
stuff(v1.str, 1, charindex(',', v1.str), '')
from (values ('[68.0,00.2]')) v(str) cross apply
(values (replace(replace(v.str, '[', ''), ']', ''))) v1(str);
This first gets rid of the '[' and ']'. Then it uses string manipulations to split the value.

Because you are - with 1 if you use this :
Select SUBSTRING('[68.0,00.2]', 2,CHARINDEX(',','[68.0,00.2]')-2) as cpu_01,
SUBSTRING('[68.0,00.2]', CHARINDEX(',','[68.0,00.2]')+1,
(LEN('[68.0,00.2]')-7)) as cpu_02
You will see the result which you need.
LEN('[68.0,00.2]) =11
So If you add -7 you will get true answer.
result :
cpu_01 cpu_02
68.0 00.2

Related

In SQL Server, how can I identify "double" strings and correct?

How can I find strings in a column that are doubled-up and correct them? I feel like there is an easy answer to this I just can't think of it.
Example:
I want to find instances of a repeating string, example "SolonSolon", and then update the column to "Solon".
Update:
They're always the same. No extra characters, but might have a space as part of the repeating value. Other examples would be...
"PlacePlace", "TreeTree", "OrangeOrange", "TravisMemorialHSTravisMemorialHS", "Texas HSTexas HS"
You can check if the string is equal to the first half replicated.
SELECT LEFT(YourCol,LEN(REPLACE(YourCol, ' ', 'x'))/2)
FROM YourTable
WHERE YourCol = REPLICATE(LEFT(YourCol,LEN(REPLACE(YourCol, ' ', 'x'))/2),2)
The reason for the REPLACE of spaces with x before calculating the LEN is because trailing spaces are ignored by this function. You can also use the technique in #lptr's answer for this but an edge case will be if the string was varchar(8000) and already 8000 characters long in which case concatenating an extra character won't do anything (LEN(SPACE(8000) + 'x') is 0).
..replace the first half of the value with an empty string..if there is nothing left..the value consists of two equal parts
select *, substring(c, 1, (len(c+'.')-1)/2)
from
(
values
('solosolo'), ('yoyo'), ('andand'), ('1212'),(' . .'),
('ababc'), ('onetwoone')
) as t(c)
where replace(c, substring(c, 1, (len(c+'.')-1)/2), '') = '';
Another alternative. The query removes inner spaces using REPLACE(str_col, ' ', ''), removes leading/traling spaces using TRIM, and checks to make sure the first half of the string equals the second half.
select left(no_spaces.str_col, v.str_len/2)
from foo f
cross apply (values (replaced trim(f.str_col), ' ', '')) no_spaces(str_col)
cross apply (values (len(no_spaces.str_col))) v(str_len)
where no_spaces.str_col=replicate(left(f.str_col, v.str_len/2), 2);

ORA-01722: invalid number - value with two decimals

I'm trying to get the max value from a text field. All but two of the values are numbers with a single decimal. However, two of the values have something like 8.2.10. How can I pull back just the integer value? The values can go higher than 9.n, so I need to convert this field into a number so that I can get the largest value returned. So all I want to get back is the 8 from the 8.2.1.
Select cast(VERSION as int) is bombing out because of those two values with a second . in them.
You may derive by using regexp_substr with \d pattern :
with tab as
(
select regexp_substr('8.2.1', '\d', 1, 1) from dual
union all
select regexp_substr('9.0.1', '\d', 1, 1) from dual
)
select * from tab;
For Oracle you must attend the value as string for retire only the part before the dot. Ex:
SELECT NVL( SUBSTR('8.2.1',0, INSTR('8.2.1','.')-1),'8.2.1') AS SR FROM DUAL;
Check than the value is repeated 3 times in the sentence, and if the value is zero or the value didn't have decimal part then it will return the value as was set.
I had to use T-SQL rather PL/SQL, but the idea is the same:
DECLARE #s VARCHAR(10);
SELECT #s='8.2.1';
SELECT CAST(LEFT(#s, CHARINDEX('.', #s) - 1) AS INT);
returns the integer 8 - note that it won't work if there are no dots because it takes the part of the string to the left of the first dot.
If my quick look at equivalent functions was correct, then in Oracle that would end up as:
SELECT CAST(SUBSTR(VERSION, 1, INSTR(VERSION, '.') - 1) AS INT)

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

Sum of data in varchar column

i have to sum element in a column(SCENARIO1) that is varchar and contain data like (1,920, 270.00, 0, NULL) but when i try to convert data into int or decimal i get this error :
"he command is wrong when converting value "4582014,00" to int type"
here is my request :
select sum( convert( int, SCENARIO1) )
from Mnt_Scenario_Exercice where code_pere='00000000'
any help please
try this
select sum(cast(replace(SCENARIO1, ',', '.') as decimal(29, 10)))
from Mnt_Scenario_Exercice
where code_pere = '00000000';
If you couldn't convert your '4582014,00' into decimal, there's a chance you have different decimal separator on your server. You could look what it is or just try '.'
4582014,00 should be a decimal
try this (I assume that youre query is working) and changed convert(int into decimal)
select sum(convert(decimal(20,2),replace(SCENARIO1, ',', '.'))) from Mnt_Scenario_Exercice where code_pere='00000000'
The problem is due to the fact that the sum function isn't decoding SCENARIO1 as containing a CSV list of numbers. The way the sum function is usually used is to sum a lot of numbers drawn from multiple rows, where each row provides one number.
Try doing it in two steps. In step 1 convert the table into first normal form perhaps by UNPIVOTING. The 1NF table will have one number per row, and will contain more rows than the initial table.
The second step is to compute the sum. If you want more than one sum in the result, use GROUP BY to create groups, and then select a sum(somecolumn). This will yield one sum for each group.
Try this, I haven't got a way to test yet, but I will test and replace if incorrect.
SELECT sum(CAST (replace(SCENARIO1, ',', '') AS INT))
FROM Mnt_Scenario_Exercice
WHERE code_pere = '00000000';
EDIT: You can use a numeric for the cast if you need 4582014,00 to be 4582014.00
SELECT sum(CAST (replace(SCENARIO1, ',', '.') AS NUMERIC(10,2)))
FROM Mnt_Scenario_Exercice
WHERE code_pere = '00000000';

Remove leading zeros

Given data in a column which look like this:
00001 00
00026 00
I need to use SQL to remove anything after the space and all leading zeros from the values so that the final output will be:
1
26
How can I best do this?
Btw I'm using DB2
This was tested on DB2 for Linux/Unix/Windows and z/OS.
You can use the LOCATE() function in DB2 to find the character position of the first space in a string, and then send that to SUBSTR() as the end location (minus one) to get only the first number of the string. Casting to INT will get rid of the leading zeros, but if you need it in string form, you can CAST again to CHAR.
SELECT CAST(SUBSTR(col, 1, LOCATE(' ', col) - 1) AS INT)
FROM tab
In DB2 (Express-C 9.7.5) you can use the SQL standard TRIM() function:
db2 => CREATE TABLE tbl (vc VARCHAR(64))
DB20000I The SQL command completed successfully.
db2 => INSERT INTO tbl (vc) VALUES ('00001 00'), ('00026 00')
DB20000I The SQL command completed successfully.
db2 => SELECT TRIM(TRIM('0' FROM vc)) AS trimmed FROM tbl
TRIMMED
----------------------------------------------------------------
1
26
2 record(s) selected.
The inner TRIM() removes leading and trailing zero characters, while the outer trim removes spaces.
This worked for me on the AS400 DB2.
The "L" stands for Leading.
You can also use "T" for Trailing.
I am assuming the field type is currently VARCHAR, do you need to store things other than INTs?
If the field type was INT, they would be removed automatically.
Alternatively, to select the values:
SELECT (CAST(CAST Col1 AS int) AS varchar) AS Col1
I found this thread for some reason and find it odd that no one actually answered the question. It seems that the goal is to return a left adjusted field:
SELECT
TRIM(L '0' FROM SUBSTR(trim(col) || ' ',1,LOCATE(' ',trim(col) || ' ') - 1))
FROM tab
One option is implicit casting: SELECT SUBSTR(column, 1, 5) + 0 AS column_as_number ...
That assumes that the structure is nnnnn nn, ie exactly 5 characters, a space and two more characters.
Explicit casting, ie SUBSTR(column,1,5)::INT is also a possibility, but exact syntax depends on the RDBMS in question.
Use the following to achieve this when the space location is variable, or even when it's fixed and you want to make a more robust query (in case it moves later):
SELECT CAST(SUBSTR(LTRIM('00123 45'), 1, CASE WHEN LOCATE(' ', LTRIM('00123 45')) <= 1 THEN LEN('00123 45') ELSE LOCATE(' ', LTRIM('00123 45')) - 1 END) AS BIGINT)
If you know the column will always contain a blank space after the start:
SELECT CAST(LOCATE(LTRIM('00123 45'), 1, LOCATE(' ', LTRIM('00123 45')) - 1) AS BIGINT)
both of these result in:
123
so your query would
SELECT CAST(SUBSTR(LTRIM(myCol1), 1, CASE WHEN LOCATE(' ', LTRIM(myCol1)) <= 1 THEN LEN(myCol1) ELSE LOCATE(' ', LTRIM(myCol1)) - 1 END) AS BIGINT)
FROM myTable1
This removes any content after the first space character (ignoring leading spaces), and then converts the remainder to a 64bit integer which will then remove all leading zeroes.
If you want to keep all the numbers and just remove the leading zeroes and any spaces you can use:
SELECT CAST(REPLACE('00123 45', ' ', '') AS BIGINT)
While my answer might seem quite verbose compared to simply SELECT CAST(SUBSTR(myCol1, 1, 5) AS BIGINT) FROM myTable1 but it allows for the space character to not always be there, situations where the myCol1 value is not of the form nnnnn nn if the string is nn nn then the convert to int will fail.
Remember to be careful if you use the TRIM function to remove the leading zeroes, and actually in all situations you will need to test your code with data like 00120 00 and see if it returns 12 instead of the correct value of 120.