I have a cell value (-4.00), where i want to replace the parenthesis '(', ')' with space or nothing at all, but it gives me error.
I tried Replace(Replace(cellvalue, ')', ' '),'(', ' ') but the error that I get is
Number value '' is not recognised.
You could use TRANSLATE:
SELECT cellvalue,
TRANSLATE(cellvalue::STRING, '()', ' ') AS paranthesis_removed,
TRY_CAST(paranthesis_removed AS NUMBER) -- if cast needed
FROM Tab
Related
I have a very specific question.
I have to build a SQL statement that builds a table where some columns are merged together. These columns shall be formatted with delimiters like '\n' or ' ' or ' - '. These delimiters shall be added only if the column before is not empty or null. This should prevent empty lines or unneeded delimiters.
Here is how I started:
SELECT
any_table.table_id,
CONCAT(any_table.text1, '\n', any_table.text2) AS text1_2,
FROM
any_table
WHERE any_table.use = 'true'
This code concats text1 and text2 as a new column text1_2 and uses a line feed as delimiter. The missing part is that line feed shall just be added if any_table.text1 is not null or empty.
Is there an elegant way in doing this with SQL?
thx
Some databases support a very handy function called concat_ws() which does exactly what you want:
CONCAT_WS('\n', NULLIF(any_table.text1, ''), NULLIF(any_table.text2, '')) AS text1_2,
In standard SQL, you can do:
TRIM(LEADING '\n' FROM CONCAT( '\n', || NULLIF(any_table.text1, ''),
'\n' || NULLIF(any_table.text2, '')
)
)
It is possible that your database supports neither of these constructs.
if you'r under SQL SERVER you can use,
SELECT id, CONCAT(colonne1 + ' - ', colonne2) FROM "table"
if you'r under Oracle : you shoul use || for concaténation like
SELECT id, CONCAT(colonne1 || ' - ', colonne2) FROM "table"
I have a table 'car_purchases' with a 'description' column. The column is a string that includes first name initial followed by full stop, space and last name.
An example of the Description column is
'Car purchased by J. Blow'
I am using 'substring_index' function to extract the letter preceding the '.' in the column string. Like so:
SELECT
Description,
SUBSTRING_INDEX(Description, '.', 1) as TrimInitial,
SUBSTRING_INDEX(
SUBSTRING_INDEX(Description, '.', 1),' ', -1) as trimmed,
length(SUBSTRING_INDEX(
SUBSTRING_INDEX(Description, '.', 1),' ', -1)) as length
from car_purchases;
I will call this query 1.
picture of the result set (Result 1) is as follows
As you can see the problem is that the 'trimmed' column in the select statement starts counting the 2nd delimiter ' ' instead of the first from the right and produces the result 'by J' instead of just 'J'. Further the length column indicates that the string length is 5 instead of 4 so WTF?
However when I perform the following select statement;
select SUBSTRING_INDEX(
SUBSTRING_INDEX('Car purchased by J. Blow', '.', 1),' ', -1); -- query 2
Result = 'J' as 'Result 2'.
As you can see from result 1 the string in column 'Description' is exactly (as far as I can tell) the same as the string from 'Result 2'. But when the substring_index is performed on the column (instead of just the string itself) the result ignores the first delimiter and selects a string from the 2nd delimiter from the right of the string.
I've racked my brains over this and have tried 'by ' and ' by' as delimiters but both options do not produce the desired result of a single character. I do not want to add further complexity to query 1 by using a trim function. I've also tried the cast function on result column 'trimmed' but still no success. I do not want to concat it either.
There is an anomaly in the 'length' column of query 1 where if I change the length function to char_length function like so:
select length(SUBSTRING_INDEX(
SUBSTRING_INDEX(Description, '.', 1),' ', -1)) as length -- result = 5
select char_length(SUBSTRING_INDEX(
SUBSTRING_INDEX(Description, '.', 1),' ', -1)) as length -- result = 4
Can anyone please explain to me why the above select statement would produce 2 different results? I think this is the reason why I am not getting my desired result.
But just to be clear my desired outcome is to get 'J' not 'by J'.
I guess I could try reverse but I dont think this is an acceptable compromise. Also I am not familiar with collation and charset principles except that I just use the defaults.
Cheers Players!!!!
CHAR_LENGTH returns length in characters, so a string with 4 2-byte characters would return 4. LENGTH however returns length in bytes, so a string with 4 2-byte characters would return 8. The discrepancy in your results (including SUBSTRING_INDEX) says that the "space" between by and J is not actually a single-byte space (ASCII 0x20) but a 2-byte character that looks like a space. To workaround this, you could try replacing all unicode characters with spaces using CONVERT and REPLACE. In this example, I have an en-space unicode character in the string between by and J. The CONVERT changes that to a ?, and the REPLACE then converts that to a space:
SELECT SUBSTRING_INDEX( SUBSTRING_INDEX("Car purchased by J. Blow", '.', 1),' ', -1)
Output:
by J
With CONVERT and REPLACE:
SELECT SUBSTRING_INDEX( SUBSTRING_INDEX(REPLACE(CONVERT("Car purchased by J. Blow" USING ASCII), '?', ' '), '.', 1),' ', -1)
Output
J
For your query, you would replace the string with your column name i.e.
SELECT SUBSTRING_INDEX( SUBSTRING_INDEX(REPLACE(CONVERT(description USING ASCII), '?', ' '), '.', 1),' ', -1)
Demo on DBFiddle
I am doing a GROUP_CONCAT to display names in the format of
Lastname1, Firstname1; Lastname2, Firstname2
There are occasions where the lastname also contains strings enclosed in curved brackets - ( and ). Since these will get displayed in the middle of the concatenated string I'm trying to move it to the end.
My solution so far is this:
GROUP_CONCAT(
DISTINCT
CASE
WHEN UPPER(psn.surname) LIKE '%INACTIVE%' THEN CONCAT(TRIM(REPLACE(psn.surname, '(Inactive)', '')), ', ', psn.firstname, ' (Inactive)')
ELSE CONCAT(psn.surname, ', ', psn.firstname)
END
ORDER BY
CASE
WHEN UPPER(psn.surname) LIKE '%INACTIVE%' THEN CONCAT(TRIM(REPLACE(psn.surname, '(Inactive)', '')), ', ', psn.firstname, ' (Inactive)')
ELSE CONCAT(psn.surname, ', ', psn.firstname)
END
ASC
SEPARATOR '; '
) AS contacts
So far this works but it only looks for a specific string, there are also cases when the string within the curved brackets isn't Inactive and I don't want to hard code all of those.
So basically how do I move a string enclosed in curved brackets to the end of a string. I imagine regex is the best solution to this problem but I don't know how to use regex.
Hmmm . . . something like this might work:
GROUP_CONCAT(DISTINCT (CASE WHEN psn.surname LIKE '%(%'
THEN CONCAT(TRIM(SUBSTRING_INDEX(psn.surname, '(', 1)), ', ',
psn.firstname, '('
SUBSTRING_INDEX(psn.surname, '(', -1)
)
ELSE CONCAT(psn.surname, ', ', psn.firstname)
END)
ORDER BY psn.surname, psn.firstname ASC SEPARATOR '; '
) AS contacts
I didn't repeat the expression for the order by. That seems like overkill.
I would like to remove the trailing spaces from the expressions in my column and add them to beginning of the expression. So for instance, I currently have the expressions:
Sample_four_space
Sample_two_space
Sample_one_space
I would like to transform this column into:
Sample_four_space
Sample_two_space
Sample_one_space
I have tried this expression:
UPDATE My_Table
SET name = REPLACE(name,'% ',' %')
However, I would like a more robust query that would work for any length of trailing spaces. Can you help me develop a query that will remove all trailing spaces and add them to the beginning of the expression?
If you know all spaces are at the end (as in your example, then you can count them and put them at the beginning:
select concat(space(length(name) - length(replace(name, ' ', ''))),
replace(name, ' ', '')
)
Otherwise the better solution is:
select concat(space( length(name) - length(trim(trailing ' ' from name)) ),
trim(trailing ' ' from name)
)
or:
select concat(space( length(name) - length(rtrim(name)) ),
rtrim(name)
)
Both these cases count the number of spaces (in or at the end of). The space() function then replicates the spaces and concat() puts them at the beginning.
I've seen a few of these questions asked but haven't spotted one that's helped!! I'm trying to select the first part of a postcode only, essentially ignoring anything after the space. the code I am using is
SUBSTRING(PostCode, 1 , CHARINDEX(' ', PostCode ) -1)
However, I am getting:
Invalid length parameter passed to the LEFT or SUBSTRING function
There's no nulls or blanks but there are some the only have the first part. Is this what causing the error and if so what's the work around?
That would only happen if PostCode is missing a space.
You could add conditionality such that all of PostCode is retrieved should a space not be found as follows
select SUBSTRING(PostCode, 1 ,
case when CHARINDEX(' ', PostCode ) = 0 then LEN(PostCode)
else CHARINDEX(' ', PostCode) -1 end)
CHARINDEX will return 0 if no spaces are in the string and then you look for a substring of -1 length.
You can tack a trailing space on to the end of the string to ensure there is always at least one space and avoid this problem.
SELECT SUBSTRING(PostCode, 1 , CHARINDEX(' ', PostCode + ' ' ) -1)
This is because the CHARINDEX-1 is returning a -ive value if the look-up for " " (space) is 0. The simplest solution would be to avoid '-ve' by adding
ABS(CHARINDEX(' ', PostCode ) -1))
which will return only +ive values for your length even if CHARINDEX(' ', PostCode ) -1) is a -ve value. Correct me if I'm wrong!
One of the selected column is null or empty.
Something else you can use is isnull:
isnull( SUBSTRING(PostCode, 1 , CHARINDEX(' ', PostCode ) -1), PostCode)