sql length(null) - sql

I have two columns: p.firstName and p.lastName.
Now I want to display the length of both names combined, the problem is, that in some fields of p.lastName the value "null" is stored.
When I try to do it like this:
LENGTH(p.firstName + p.lastName)
I get an error:
ORA-01722 invalid number
However, if I split it up
LENGTH(p.firstName) + LENGTH(p.lastName)
it doesn't give me an error message. But the length of the sum is NULL, even if the firstName does have a few characters. The NULL of p.LastName breaks it so to say.
Anyone has an idea?

You can Use IFNULL(), ISNULL(), COALESCE(), and NVL() Functions
SELECT LENGTH(COALESCE(p.firstName,'') + COALESCE(p.lastName,'')) AS Len FROM TableName
OR
SELECT LENGTH(ISNULL(p.firstName,'') + ISNULL(p.lastName,'')) AS Len FROM TableName
OR
SELECT LENGTH(IFNULL(p.firstName,'') + IFNULL(p.lastName,'')) AS Len FROM TableName
OR
SELECT LENGTH(NVL(p.firstName,'') + NVL(p.lastName,'')) AS Len FROM TableName
OR
SELECT LENGTH(p.firstName || p.lastName) AS Len FROM TableName

You may to concat columns instead using || operator:
LENGTH(p.firstName || p.lastName)
Example:
select ('abc'||null||'d') from dual; -- abcd
select length('abc'||null||'d') from dual; -- 4

Try this
select case when p.firstname is null then 0 else length(p.firstName) end +
case when p.lastName is null then 0 else
length(nickname) end from p

Oracle usually treats an empty string as NULL:
COALESCE(LENGTH(p.firstName), 0) + COALESCE(LENGTH(p.lastName),0)

I think it is much better to use it this way...
SELECT LENGTH(ISNULL(p.firstName,'') + ISNULL(p.lastName,'')) AS length FROM TableName

NOTE: Oracle behaves differently in the dealing of blank characters:
---------Oracle
SELECT LENGTH('') , LENGTH(null) FROM DUAL
--result: null,null
---------Postgress
SELECT LENGTH('') , LENGTH(null)
--result: 0,null
---------SQL Server
SELECT LEN('') , LEN(null)
--result: 0,null
---------MySQL
SELECT LENGTH('') , LENGTH(null)
--result: 0,null

Related

Sql Bigquery - concat two columns into a new column

I want to concat two columns shown below into one new column.
I'm using this query:
SELECT
CONCAT( A_Bill_ID , ' ', B_BILL_ID ) AS BILL_ID
FROM
`table.tmp_140222`
From this query, the result will be like this.
My problem is I want to concat only columns that don't have a similar value so that the new column value will not duplicate two times. From the above result, the ID is duplicated since both of the columns has the same value.
Can anyone help me?
Thanks
You can use a case statement like this -
SELECT
case when A_Bill_ID = B_BILL_ID then a_bill_Id
else CONCAT(A_Bill_ID , ' ', B_BILL_ID )
end AS BILL_ID
FROM `table.tmp_140222`
If there are Null values in the initial columns, you can use IFNULL or COALEASE to replace that with an empty string. But in this case, I would suggest using this without a delimiter or writing multiple 'when' statements to avoid tailing spaces in the final column -
SELECT
case when A_Bill_ID = B_BILL_ID then a_bill_Id
else CONCAT(IFNULL(A_Bill_ID), ''), "", IFNULL(B_BILL_ID, ''))
end AS BILL_ID
FROM `table.tmp_140222`
select if (
a_bill_id = b_bill_id,
a_bill_id,
concat(a_bill_id , ' ', b_bill_id )
) as bill_id
from your_table
... shows null value ....
select if (
a_bill_id = b_bill_id or (a_bill_id = b_bill_id) is null,
coalesce(a_bill_id, b_bill_id),
concat(a_bill_id , ' ', b_bill_id )
) as bill_id
from your_table

SQL: select the last values before a space in a string

I have a set of strings like this:
CAP BCP0018 36
MFP ACZZ1BD 265
LZP FEI-12 3
I need to extract only the last values from the right and before the space, like:
36
265
3
how will the select statement look like? I tried using the below statement, but it did not work.
select CHARINDEX(myField, ' ', -1)
FROM myTable;
Perhaps the simplest method in SQL Server is:
select t.*, v.value
from t cross apply
(select top (1) value
from string_split(t.col, ' ')
where t.col like concat('% ', val)
) v;
This is perhaps not the most performant method. You probably would use:
select right(t.col, charindex(' ', reverse(t.col)) - 1)
Note: If there are no spaces, then to prevent an error:
select right(t.col, charindex(' ', reverse(t.col) + ' ') - 1)
Since you have mentioned CHARINDEX() in question, I am assuming you are using SQL Server.
Try below
declare #table table(col varchar(100))
insert into #table values('CAP BCP0018 36')
insert into #table values('MFP ACZZ1BD 265')
insert into #table values('LZP FE-12 3')
SELECT REVERSE(LEFT(REVERSE(col),CHARINDEX(' ',REVERSE(col)) - 1)) FROM #table
Functions used
CHARINDEX ( expressionToFind , expressionToSearch ) : returns position of FIRST occurence of an expression inside another expression.
LEFT ( character_expression , integer_expression ) : Returns the left part of a character string with the specified number of characters.
REVERSE ( string_expression ) : Returns the reverse order of a string value

Separate fullname into first and last, and remove 'junk'

Wasn't sure of the best way to word this. So I have a column with names, as below:
SalesPerson_Name
----------------
Undefined - 0
Sam Brett-sbrett
Kelly Roberts-kroberts
Michael Paramore-mparamore
Alivia Lawler-alawler
Ryan Hooker-rhooker
Heather Alford-halford
Cassandra Blegen-cblegen
JD Holland-jholland
Vendor Accounts-VENDOR
Other Accounts-OTHER
Getting the names separated is easy enough with PARSENAME and REPLACE functions, but where I'm running into a pickle is with getting rid of the 'junk' at the end:
SELECT SalesPerson_Key
,SalesPerson_Name
,CASE
WHEN PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 2) IS NULL
THEN PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 1)
ELSE PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 2)
END AS FirstName
,CASE
WHEN PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 2) IS NULL
THEN NULL
ELSE PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 1)
END AS LastName
FROM Salesperson
RESULTS FOR LASTNAME COLUMN:
LastName
--------
0
Brett-sbrett
Roberts-kroberts
Paramore-mparamore
Lawler-alawler
Hooker-rhooker
Alford-halford
Blegen-cblegen
Holland-jholland
Accounts-VENDOR
Accounts-OTHER
Specifically, I want to get rid of the text (userid) at the end of the last name. If the names were the same length, I could just use a RIGHT function, but they vary in length. Ideas?
select left(PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 1), len(SalesPerson_Name)-CHARINDEX('-',SalesPerson_Name)-1)
You are getting charindex of - and taking the left string of it.
If you just want to remove the last word (username) you can use a query like this
select
rtrim(
substring(
SalesPerson_Name,
1,
charindex('-',SalesPerson_Name,1)-1
)
)
from Salesperson
The charindex function locates the occurrence of the character/s you are looking for.
Consider whether hyphen is followed by a space or not, and split depending on these two cases
with Salesperson( SalesPerson_Name ) as
(
select 'Undefined - 0' union all
select 'Sam Brett-sbrett' union all
select 'Kelly Roberts-kroberts' union all
select 'Michael Paramore-mparamore' union all
select 'Alivia Lawler-alawler'
)
select case when substring(SalesPerson_Name,charindex(' ',SalesPerson_Name)+1,1) = '-' then
substring(SalesPerson_Name,charindex(' ',SalesPerson_Name)+3,len(SalesPerson_Name))
else
substring(SalesPerson_Name,charindex(' ',SalesPerson_Name)+1,len(SalesPerson_Name))
end as last_name
from Salesperson s;
last_name
------------------
0
Brett-sbrett
Roberts-kroberts
Paramore-mparamore
Lawler-alawler

sql concatenation with blank cells

So I am extracting data from one table to another
SELECT *
LTRIM(ADRESSE + ',' + ADRESSE2) AS ADDRESS12
FROM [Homestore].[dbo].[CLIENT]
Issue is that if the cells are blank i still get a comma ,
I have tried using & instead of + but nvarchar is incompatible in the '&' operator. Any ideas how I only insert the comma if there is something to concatenate?
You want the equivalent of CONCAT_WS() in other databases. You can do this with STUFF() and some string logic in SQL Server:
SELECT c.*
STUFF( (COALESCE(',' + ADRESSE, '') +
COALESCE(',' + ADRESSE2, '') +
), 1, 1, ''
) AS ADDRESS12
FROM [Homestore].[dbo].[CLIENT] c;
This structure is convenient, because you can just add more COALESCE() expressions for more columns.
use case expression
SELECT *, LTRIM(ADRESSE + case when ADRESSE is not null then ',' end + ADRESSE2) AS ADDRESS12
FROM [Homestore].[dbo].[CLIENT]
use case when for null checking
SELECT *
LTRIM(ADRESSE + case when ADRESSE2 is not null then
',' else '' end + ADRESSE2) AS ADDRESS12
FROM [Homestore].[dbo].[CLIENT]

SQL Server 2008: How to find trailing spaces

How can I find all column values in a column which have trailing spaces? For leading spaces it would simply be
select col from table where substring(col,1,1) = ' ';
You can find trailing spaces with LIKE:
SELECT col FROM tbl WHERE col LIKE '% '
SQL Server 2005:
select col from tbl where right(col, 1) = ' '
As a demo:
select
case when right('said Fred', 1) = ' ' then 1 else 0 end as NoTrail,
case when right('said Fred ', 1) = ' ' then 1 else 0 end as WithTrail
returns
NoTrail WithTrail
0 1
This is what worked for me:
select * from table_name where column_name not like RTRIM(column_name)
This will give you all the records that have trailing spaces.
If you want to get the records that have either leading or trailing spaces then you could use this:
select * from table_name where column_name not like LTRIM(RTRIM(column_name))
A very simple method is to use the LEN function.
LEN will trim trailing spaces but not preceeding spaces, so if your LEN() is different from your LEN(REVERSE()) you'll get all rows with trailing spaces:
select col from table where LEN(col) <> LEN(REVERSE(col));
this can also be used to figure out how many spaces you have for more advanced logic.
SELECT * FROM tbl WHERE LEN(col) != DATALENGTH(col)
Should work also.
There's a few different ways to do this...
My favorite option, assuming your intention is to remove any leading and / or trailing spaces, is to execute the following, which will dynamically create the T-SQL to UPDATE all columns with an unwanted space to their trimmed value:
SELECT
'UPDATE [<DatabaseName>].[dbo].['+TABLE_NAME+']
SET ['+COLUMN_NAME+']=LTRIM(RTRIM(['+COLUMN_NAME+']))
WHERE ['+COLUMN_NAME+']=LTRIM(RTRIM(['+COLUMN_NAME+']));'+CHAR(13)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '<TableName>%'
AND DATA_TYPE!='date'
ORDER BY TABLE_NAME,COLUMN_NAME
If you really need to identify them though, try one of these queries:
SELECT *
FROM [database].[schema].[table]
WHERE [col1]!=LTRIM(RTRIM([col1]))
More dynamic SQL:
SELECT 'SELECT ''['+TABLE_NAME+'].['+COLUMN_NAME+']'',*
FROM [<your database name>].[dbo].['+TABLE_NAME+']
WHERE ['+COLUMN_NAME+'] LIKE ''% ''
OR ['+COLUMN_NAME+'] LIKE '' %'';
GO
'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '<filter table name as desired>%'
AND DATA_TYPE!='date'
Here's an alternative to find records with leading or trailing whitespace, including tabs etc:
SELECT * FROM tbl WHERE NOT TRIM(col) = col
Try this:
UPDATE Battles
SET name = CASE WHEN (LEN(name+'a')-1)>LEN(RTRIM(name))
THEN REPLICATE(' ', (LEN(name+'a')-1)- LEN(RTRIM(name)))+RTRIM(name)
ELSE name
END
Spaces are ignored in SQL Server so for me even the leading space was not working .
select col from table where substring(col,1,1) = ' '
wont work if there is only one space (' ') or blank ('')
so I devised following:
select * from [table] where substring(REPLACE(col, ' ', '#'),1,1) = '#'
Here is another alternative for trailing spaces.
DECLARE #VALUE VARCHAR(50) = NULL
DECLARE #VALUE VARCHAR(50) = ' '
IF ((#VALUE IS NOT NULL) AND (LTRIM(RTRIM(#VALUE)) != ''))
BEGIN
SELECT 'TRUE'
END
ELSE
BEGIN
SELECT 'FALSE'
END
I have found the accepted answer a little bit slower:
SELECT col FROM tbl WHERE col LIKE '% ';
against this technique:
SELECT col FROM tbl WHERE ASCII(RIGHT([value], 1)) = 32;
The idea is to get the last char, but compare its ASCII code with the ASCII code of space instead only with ' ' (space). If we use only ' ' space, an empty string will yield true:
DECLARE #EmptyString NVARCHAR(12) = '';
SELECT IIF(RIGHT(#EmptyString, 1) = ' ', 1, 0); -- this returns 1
The above is because of the Microsoft's implementation of string comparisons.
So, how fast exactly?
You can try the following code:
CREATE TABLE #DataSource
(
[RowID] INT PRIMARY KEY IDENTITY(1,1)
,[value] NVARCHAR(1024)
);
INSERT INTO #DataSource ([value])
SELECT TOP (1000000) 'text ' + CAST(ROW_NUMBER() OVER(ORDER BY t1.number) AS VARCHAR(12))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
UPDATE #DataSource
SET [value] = [value] + ' '
WHERE [RowID] = 100000;
SELECT *
FROM #DataSource
WHERE ASCII(RIGHT([value], 1)) = 32;
SELECT *
FROM #DataSource
WHERE [value] LIKE '% ';
On my machine there is around 1 second difference:
I have test it on table with 600k rows, but larger size, and the difference was above 8 seconds. So, how fast exactly will depend on your real case data.
Another way to achieve this by using CHARINDEX and REVERSE like below:
select col1 from table1
WHERE charindex(' ', reverse(col1)) = 1
See example Here
Simple use below query to get values having any number of spaces in begining or at end of values in column.
select * from table_name where column_name like ' %' or column_name like '% ';
We can try underscore to find the entries which are blanks,though not an accurate solution like using '% %' or ' ', But I could find entries which are blanks.
select col_name from table where col_name like '_'