Choose the non null column per row - sql

I'm working with a table which has "Name", "FirstName", and "Surname" fields.
"Name" was used years ago but is still supported.
Today though the "FirstName" and "Surname" fields are used instead.
Here's what I'd like to do for my query on this table. If FirstName and/or Surname are not Null then I want them returned for the row, otherwise I want Name.
FirstName and Surname can be concatenated with a space between, giving just a single field in the returned result. Or maybe you have a better solution.
Thanks you!
Barry

This can be done by either using COALESCE
SELECT COALESCE(Firstname + ' ' + Surname, Name)
FROM ATable
or using ISNULL
SELECT ISNULL(Firstname + ' ' + Surname, Name)
FROM ATable
If Firstname or Surname can be NULL and you want to return one of these, you would use COALESCE
SELECT COALESCE(Firstname + ' ' + Surname, Firstname, Surname, Name)
FROM ATable
COALESCE
Returns the first nonnull expression among its arguments.

SELECT CASE
WHEN [FirstName] IS NULL OR [Surname] IS NULL THEN [Name]
ELSE [FirstName] + ' ' + [Surname]
END AS [Name]
FROM MyTable

Related

SQL: Combine First Name and Last Name columns but if Null change to 'Name Not Provided'

I'm currently building a simple view and need to combine both the First Name and Last Name columns to create a new Customer column. If a First Name and Last Name are not provided I'd like to change this new combined value to 'Name Not Provided'.
Currently I use a simple select statement:
LastName + ', ' + FirstName AS Customer
which appears to work fine for combing the data but if the data doesn't exist, it will just return ', '. How do I go about changing this so it returns 'Name Not Provided'?
SELECT Customer = CASE WHEN FirstName IS NULL AND LastName IS NULL
THEN 'Name Not Provided'
WHEN FirstName IS NULL AND LastName IS NOT NULL
THEN LastName
WHEN FirstName IS NOT NULL AND LastName IS NULL
THEN FirstName
ELSE LastName + ', ' + FirstName END
FROM dbo.TableName
Demo
SET CONCAT_NULL_YIELDS_NULL ON
SELECT ISNULL(LastName + ', ' + FirstName, 'Name Not Provided') AS Customer
Microsoft's ISNULL() function is used to specify how we want to treat NULL values.
The following query will return a default text if FirstName is NULL.
SELECT (ISNULL(FirstName,'First name is null')) AS Customer

Combining two column's data into one column in SQL?

I am trying to combine Last name, first name and middle name into single sort name column in a SQL statement. Sometime middle name will be NULL, and if that's the case, the sort name is showing NULL.
How to handle this?
SELECT TOP 500
Last_Name, First_Name, Middle_Name,
[Last_Name] + ',' + [First_Name] + ' ' + [Middle_Name] AS SORT_NAME
FROM [dbo].[usr_CUSTOMER]
ORDER BY SORT_NAME
Results:
Last_Name First_Name MiddleName Sort_Name
Aa Robert NULL NULL
But I want to see sort_name to be 'Aa,Robert'.
COALESCE:
COALESCE([Last_Name], '') + ',' + COALESCE([First_Name], '') + ' ' +
COALESCE(
[Middle_Name], '') AS SORT_NAME
Of course, this will leave ugly commas when last name or both first and middle are empty, so your actual code will need to be a bit more clever.
Use the ISNULL() function - it replaces a NULL value with something you define:
SELECT TOP 500
Last_Name, First_Name, Middle_Name,
[Last_Name] + ',' + [First_Name] + ' ' + ISNULL([Middle_Name], '') as SORT_NAME
FROM [dbo].[usr_CUSTOMER]
ORDER BY SORT_NAME
You can use the ISNULL function
ISNULL ( check_expression , replacement_value )
Docs : http://msdn.microsoft.com/en-us/library/ms184325.aspx
Note that I moved the space separating First and Middle name inside the COALESCE so that you avoid having a trailing space when Middle name is NULL.
..., [Last_Name]+ ','+ [First_Name] + COALESCE(' '+ [Middle_Name],'') as SORT_NAME...
Try
CONCAT(firstname,' ', LastName,' ', MiddleName) AS Full_Name

How to convert two nvarchar rows into one when one of the row is null

sorry if this is a duplicate to one of existing questions (it's so simple but I can't figure it out, I'm new).
I need to migrate some data from one table to another (different structures).
Table A have Firstname and LastName columns.
Table B have Name column
I want to do
SELECT Firstname + ' ' + LastName As Name FROM TableA
But the problem is that in table B, some rows have null value for firstname or lastname but not both (Lazy user).
When I import them into table B, the query fails because Name column is non-nullable in my new design and when I test the statement above, if firstname or lastname is null, the concated value is null.
From the reading that I've done, this is expected behavior but what can I do to get around this?
I want to save firstname or lastname if the other is null.
SELECT RTRIM(LTRIM(ISNULL(Firstname ,'') + ' ' + ISNULL(LastName,''))) AS Name
FROM TableA
This can be done with a single colaesce (return first non-null) & no need to mess about with spaces.
select
coalesce(firstname + ' ' + lastname, firstname, lastname)
from TableA
use coalesce or isnull
select COALESCE(FirstNAme, '') + ' ' + COALESCE(LastName, '') as name from TableA
SELECT isnull (Firstname, '') + ' ' isnull (LastName, '') as Name
FROM TableA

How do I get first name and last name as whole name in a MYSQL query?

I want to be able to do something like this
SELECT `first_name` + " " + `last_name` as `whole_name` FROM `users`
So basically I get one column back whole_name which is first_name and last_name concatenated together with a (space).
How do I do that in SQL, or more specifically, MySQL ?
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_concat-ws
SELECT CONCAT_WS(" ", `first_name`, `last_name`) AS `whole_name` FROM `users`
You can use a query to get the same:
SELECT CONCAT(FirstName , ' ' , MiddleName , ' ' , Lastname) AS Name FROM TableName;
Note: This query return if all columns have some value if anyone is null or empty then it will return null for all, means Name will return "NULL"
To avoid above we can use the IsNull keyword to get the same.
SELECT Concat(Ifnull(FirstName,' ') ,' ', Ifnull(MiddleName,' '),' ', Ifnull(Lastname,' ')) FROM TableName;
If anyone containing null value the ' ' (space) will add with next value.
When you have three columns : first_name, last_name, mid_name:
SELECT CASE
WHEN mid_name IS NULL OR TRIM(mid_name) ='' THEN
CONCAT_WS( " ", first_name, last_name )
ELSE
CONCAT_WS( " ", first_name, mid_name, last_name )
END
FROM USER;
rtrim(lastname)+','+rtrim(firstname) as [Person Name]
from Table
the result will show lastname,firstname as one column header !

How do I perform a GROUP BY on an aliased column in SQL Server?

I'm trying to perform a group by action on an aliased column (example below) but can't determine the proper syntax.
SELECT LastName + ', ' + FirstName AS 'FullName'
FROM customers
GROUP BY 'FullName'
What is the correct syntax?
Extending the question further (I had not expected the answers I had received) would the solution still apply for a CASEed aliased column?
SELECT
CASE
WHEN LastName IS NULL THEN FirstName
WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName
END AS 'FullName'
FROM customers
GROUP BY
LastName, FirstName
And the answer is yes it does still apply.
You pass the expression you want to group by rather than the alias
SELECT LastName + ', ' + FirstName AS 'FullName'
FROM customers
GROUP BY LastName + ', ' + FirstName
This is what I do.
SELECT FullName
FROM
(
SELECT LastName + ', ' + FirstName AS FullName
FROM customers
) as sub
GROUP BY FullName
This technique applies in a straightforward way to your "edit" scenario:
SELECT FullName
FROM
(
SELECT
CASE
WHEN LastName IS NULL THEN FirstName
WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName
END AS FullName
FROM customers
) as sub
GROUP BY FullName
Unfortunately you can't reference your alias in the GROUP BY statement, you'll have to write the logic again, amazing as that seems.
SELECT LastName + ', ' + FirstName AS 'FullName'
FROM customers
GROUP BY LastName + ', ' + FirstName
Alternately you could put the select into a subselect or common table expression, after which you could group on the column name (no longer an alias.)
Sorry, this is not possible with MS SQL Server (possible though with PostgreSQL):
select lastname + ', ' + firstname as fullname
from person
group by fullname
Otherwise just use this:
select x.fullname
from
(
select lastname + ', ' + firstname as fullname
from person
) as x
group by x.fullname
Or this:
select lastname + ', ' + firstname as fullname
from person
group by lastname, firstname -- no need to put the ', '
The above query is faster, groups the fields first, then compute those fields.
The following query is slower (it tries to compute first the select expression, then it groups the records based on that computation).
select lastname + ', ' + firstname as fullname
from person
group by lastname + ', ' + firstname
Given your edited problem description, I'd suggest using COALESCE() instead of that unwieldy CASE expression:
SELECT FullName
FROM (
SELECT COALESCE(LastName+', '+FirstName, FirstName) AS FullName
FROM customers
) c
GROUP BY FullName;
My guess is:
SELECT LastName + ', ' + FirstName AS 'FullName'
FROM customers
GROUP BY LastName + ', ' + FirstName
Oracle has a similar limitation, which is annoying. I'm curious if there exists a better solution.
To answer the second half of the question, this limitation applies to more complex expressions such as your case statement as well. The best suggestion I've seen it to use a sub-select to name the complex expression.
You can use CROSS APPLY to create an alias and use it in the GROUP BY clause, like so:
SELECT FullName
FROM Customers
CROSS APPLY (SELECT LastName + ', ' + FirstName AS FullName) Alias
GROUP BY FullName
SELECT
CASE
WHEN LastName IS NULL THEN FirstName
WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName
END AS 'FullName'
FROM
customers
GROUP BY
LastName,
FirstName
This works because the formula you use (the CASE statement) can never give the same answer for two different inputs.
This is not the case if you used something like:
LEFT(FirstName, 1) + ' ' + LastName
In such a case "James Taylor" and "John Taylor" would both result in "J Taylor".
If you wanted your output to have "J Taylor" twice (one for each person):
GROUP BY LastName, FirstName
If, however, you wanted just one row of "J Taylor" you'd want:
GROUP BY LastName, LEFT(FirstName, 1)
If you want to avoid the mess of the case statement being in your query twice, you may want to place it in a User-Defined-Function.
Sorry, but SQL Server would not render the dataset before the Group By clause so the column alias is not available. You could use it in the Order By.
In the old FoxPro (I haven't used it since version 2.5), you could write something like this:
SELECT LastName + ', ' + FirstName AS 'FullName', Birthday, Title
FROM customers
GROUP BY 1,3,2
I really liked that syntax. Why isn't it implemented anywhere else? It's a nice shortcut, but I assume it causes other problems?
SELECT
CASE WHEN LastName IS NULL THEN FirstName
WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName
END AS 'FullName'
FROM customers GROUP BY 1`
For anyone who finds themselves with the following problem (grouping by ensuring zero and null values are treated as equals)...
SELECT AccountNumber, Amount AS MyAlias
FROM Transactions
GROUP BY AccountNumber, ISNULL(Amount, 0)
(I.e. SQL Server complains that you haven't included the field Amount in your Group By or aggregate function)
...remember to place the exact same function in your SELECT...
SELECT AccountNumber, ISNULL(Amount, 0) AS MyAlias
FROM Transactions
GROUP BY AccountNumber, ISNULL(Amount, 0)