Result of substring not work when use CASE statement - postgresql-9.5

Column's type : jsonb
Here table's data:
Now I want to convert 2.5kg to 2500. And remove rest substring.
Here query:
select id,
case when title_en ~ 'kg$'
then
cast(replace(substring(title_en
from
(length(title_en) - position(' ' in reverse(title_en)) + 1) -- last space position
for
(position('kg' in title_en)) - (length(title_en) - position(' ' in reverse(title_en)) + 1) -- count of chars to extract
),',','.')::float * 1000 as text)
else title_en
end,
weight_qty, options_weight from result_table
I converted all column to text type.
Here result:
Nice. It's correct result. Now I need to filter record content 2500 in column title_en
I try this (show only where clause)
weight_qty, options_weight from result_table
where
title_en ~ '2500'
But result is empty.
But if I try with old value (2.5kg) than it correct show one record.
weight_qty, options_weight from result_table
where
title_en ~ '2.5kg'
Here result:
Why not work with new value (2500) ?

Related

Count spaces before a string value SQL

so I have a table TEST with 2 columns - id and value. I would like a count of the number of spaces before a specific string value.
id value
1 AB CD EFD RA
I would like a query to count the number of spaces in the value column to the left of "EFD". In this case it should be 2.
Thanks!
I tried:
select ID,
VALUE,
regexp_substr(Value, 'EFD') AS "SUBSTRING",
regexp_instr(Value, 'EFD') AS "POSITION"
I would like to get the position of EFD in this array as well. I should get 3.
select id, value,
regexp_substr(Value, 'EFD') AS substring,
regexp_count(substring(Value, 1, regexp_instr(Value, 'EFD')-1), ' ') AS spaces_before_EFD,
regexp_instr(Value, 'EFD') AS position
from test;

Oracle - Get all characters before the nth occurrence of a character

I am trying to get a query where I get all characters from a string before the 'n'the occurence of a character.
Say I could have the following strings:
'123456,123456,123456'
'123456'
'123456,123456,123456,123456,123456,123456'
'123456,123456,123456,123456,123456,123456,123456'
Now I want my query to always return everything before the 5th occurence of the comma,
Result:
'123456,123456,123456'
'123456'
'123456,123456,123456,123456,123456'
'123456,123456,123456,123456,123456'
I've been trying with some substr or regexes, but I can't get my head around this.
INSTR function has exactly what you need to find the position of n-th substring - see the occurrence parameter.
To get the part of a string till this location use SUBSTRING.
To avoid the case when there is no Nth symbol, use NVL (or COALESCE).
For example (replace 5 with N and insert your columns):
SELECT NVL(
SUBSTR(YOUR_COLUMN, 1,
INSTR(YOUR_COLUMN,',',1,5) -1),
YOUR_COLUMN)
FROM YOUR_TABLE;
You can do that:
define string_value='123456,123456';
select CASE
WHEN (length('&string_value') - length(replace('&string_value',',',null))) >=5
THEN SUBSTR('&string_value',0,INSTR('&string_value',',',1,5)-1)
ELSE '&string_value'
END as output
from dual;
output:
123456,123456
define string_value='123456,123456,123456,123456,123456,123456';
select CASE
WHEN (length('&string_value') - length(replace('&string_value',',',null))) >=5
THEN SUBSTR('&string_value',0,INSTR('&string_value',',',1,5)-1)
ELSE '&string_value'
END as output
from dual;
output:
123456,123456,123456,123456,123456
This will work event if the number of character between the commas is not always the same.

Insert a negative value with minus sign at end

I want to insert a value into an sql server 2008 table.
The value are like 20.00- , 10.00-
The minus sign is at the end of the value.
How can I achieve this?
How about using something like this?
SELECT REPLACE(CAST(-456.00 AS VARCHAR(10)),'-','') + '-'
Where 456.00 is your value
You could insert raw data into a staging table first. Then you could either convert the values in the staging table and insert them afterwards into the actual table, or insert and convert at the same time.
Here's how you could go about the conversion.
For every input value, you would need to check if it has a minus. If it does, then one character should be deleted at the last position and one character should be inserted at the first position. Otherwise nothing should be deleted or inserted.
So, essentially you can have an indication in the form of 1 or 0 and use that number to determine how many characters to insert or delete.
There are various methods of obtaining that 1/0 result.
For instance, you could take the input value's last character as a substring and use CHARINDEX to search for - within that substring:
CHARINDEX('-', LEFT(InputValue, LEN(InputValue)))
If the last character of InputValue is '-', the CHARINDEX will return 1, otherwise it will return 0.
Another method, also using CHARINDEX, would be to go like this:
CAST(CHARINDEX('-', InputValue) AS bit)
If InputValue has a minus, CHARINDEX will return a positive result and CAST will convert it to 1. If there is no minus, CHARINDEX will give you a 0, which will stay 0 after the cast.
Now you can use the expression's result to determine:
whether to delete the last character or not:
STUFF(InputValue, LEN(InputValue), CAST(CHARINDEX('-', InputValue) AS bit), '')
and
whether to prefix the value with a '-':
REPLICATE('-', CAST(CHARINDEX('-', InputValue) AS bit))
That is, the complete expression is this:
REPLICATE('-', CAST(CHARINDEX('-', InputValue) AS bit)) +
STUFF(InputValue, LEN(InputValue), CAST(CHARINDEX('-', InputValue) AS bit), '')
In the final statement you could also use CROSS APPLY to avoid repetition of the emphasised sub-expression, something aloong the lines of this (assuming you will choose to do insertion + processing):
INSERT INTO dbo.TargetTable (columns)
SELECT
...
REPLICATE('-', x.HasMinus) + STUFF(InputValue, LEN(InputValue), x.HasMinus, ''),
...
FROM dbo.StagingTable
CROSS APPLY (SELECT CAST(CHARINDEX('-', InputValue) AS bit)) AS x (HasMinus)
;
It is long but :
select IIF(ISNUMERIC(IIF(RIGHT(RTRIM('20.55-'), 1) = '-', '-' + REPLACE('20.55-', '-',''), '20.55-')) = 1, CONVERT(decimal(7,3), IIF(RIGHT(RTRIM('20.55-'), 1) = '-', '-' + REPLACE('20.55-', '-',''), '20.55-')), NULL)
Simply :
Select CASE WHEN LEFT(InputValue,1) = '-' THEN '-' ELSE '' END + REPLACE(InputValue,'-','')
You may need to Cast it as money (or numeric or decimal)

Teradata : Sum up values in a column

Problem Statement
Example is shown in below image :
The last 2 rows have the patterns like "1.283 2 3" in a single cell. The numbers are seperated by space in the column. We need to add those nos and represent in the format given in Output.
So, the cell having "1.283 2 3" must be converted to 6.283
Challenges facing :
The column values are in string format.
Add nos after casting them into integer
Donot want to take data in UNIX box and manipulate the same.
In TD14 there would be a built-in table UDF named STRTOK_SPLIT_TO_TABLE, before you need to implement your own UDF or use a recursive query.
I modified an existing string splitting script to use blanks as delimiter:
CREATE VOLATILE TABLE Strings
(
groupcol INT NOT NULL,
string VARCHAR(991) NOT NULL
) ON COMMIT PRESERVE ROWS;
INSERT INTO Strings VALUES (1,'71.792');
INSERT INTO Strings VALUES (2,'71.792 1 2');
INSERT INTO Strings VALUES (3,'1.283 2 3');
WITH RECURSIVE cte
(groupcol,
--string,
len,
remaining,
word,
pos
) AS (
SELECT
GroupCol,
--String,
POSITION(' ' IN String || ' ') - 1 AS len,
TRIM(LEADING FROM SUBSTRING(String || ' ' FROM len + 2)) AS remaining,
TRIM(SUBSTRING(String FROM 1 FOR len)) AS word,
1
FROM strings
UNION ALL
SELECT
GroupCol,
--String,
POSITION(' ' IN remaining)- 1 AS len_new,
TRIM(LEADING FROM SUBSTRING(remaining FROM len_new + 2)),
TRIM(SUBSTRING(remaining FROM 1 FOR len_new)),
pos + 1
FROM cte
WHERE remaining <> ''
)
SELECT
groupcol,
-- remove the NULLIF to get 0 for blank strings
SUM(CAST(NULLIF(word, '') AS DECIMAL(18,3)))
FROM cte
GROUP BY 1
This might use a lot of spool, hopefully you're not running that on a large table.

Get all characters before space in MySQL

I would like to get all the characters in a field before a space
For example, if field1 is "chara ters"
I want it to return "chara"
What would this select statement look like?
SELECT LEFT(field1,LOCATE(' ',field1) - 1)
Note that if the string in question contains no spaces, this will return an empty string.
Below is another method that works and may seem a bit simpler to some. It uses the SUBSTRING_INDEX MySQL function. A 1 returns everything before the first space, and a -1 returns everything after the last space.
This returns 'chara':
SELECT SUBSTRING_INDEX( field1, ' ', 1 )
This returns 'ters':
SELECT SUBSTRING_INDEX( field1, ' ', -1 )
Details
A positive value will look for your specified character from the start of the string, and a negative value will start from the end of the string. The value of the number indicates the quantity of your specified character to look for before returning the remaining piece of the string. If the character you are searching for does not exist, the entire field value will be returned.
In this case, a -2 would return everything to the right of the second to last space, which doesn't exist in this example, so the entire field value will be returned.
You would need some string operations for that. Assuming every field has at least one space character:
SELECT SUBSTR(field1, 0, LOCATE(' ', field1)) FROM your_table;
Safe approach:
SELECT IF(
LOCATE(' ', field1),
SUBSTR(field1, 0, LOCATE(' ', field1)),
field1
) FROM your_table;
For a generalized approach that returns the nth value (one-based index) from a column containing delimited values:
select SUBSTRING_INDEX(SUBSTRING_INDEX(my_column,#delimiter,#index),#delimiter,-1) from my_table;
This will return the entire column contents if the delimiter does not exist, and the last field if the index value exceeds the number of fields.
For instance, if my_column contains 'foo bar baz' and you want the 2nd field:
select SUBSTRING_INDEX(SUBSTRING_INDEX(my_column,' ',2),' ',-1) from my_table;
will return bar, and if you specify the 4th field (which does not exist):
select SUBSTRING_INDEX(SUBSTRING_INDEX(my_column,' ',4),' ',-1) from my_table;
will return baz (the last field).