Data is "lastName, FirstName". I need to write it as "FirstName LastName" - sql

Running sql server 2008 The title says it, but in my select statement I have this
COALESCE( ca.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)')
,ca2.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)'))
AS IR_Name
and it returns lastName, FirstName
This becomes a problem when exporting to a csv as it creates two separate columns and what not.
I somehow have to figure out how to have the string be firstName lastName, no commas, and putting the firstName first.

SELECT PARSENAME(REPLACE('John , Doe', ',', '.'), 1) + ' ' + PARSENAME(REPLACE('John , Doe', ',', '.'), 2)
this will switch 'John , Doe' to 'Doe John'. Now, you just need replace the 'John, Doe" with the
COALESCE(ca.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)'),ca2.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)')) AS IR_Name

Another way to do this is by using string functions:
select (case when IR_Name like '%,%'
then (ltrim(rtrim(substring(IR_NAME, charindex(',', IR_NAME)+1, 1000))) + ' ' +
ltrim(rtrim(left(IR_Name, charindex(',', IR_NAME) - 1)))
)
else IR_NAME
end) t
from (select COALESCE( ca.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)')
,ca2.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)'))
AS IR_Name
. . .
) t
The trimming functions are to remove extra spaces.
The parsename solution is clever. But, it looks strange since parsename is designed for multipart naming conventions, with up to four parts separated by periods.

Related

RIGHT, LEFT and CHARINDEX not performing as expected

I am trying to reorder a column of names that is in the form lastname, firstname to firstname lastname. The original column is NAME_BAT and I have confirmed there are no leading or trailing spaces. Here is my SQL code:
SELECT TOP (100) NAME_BAT
, LTRIM(RIGHT(NAME_BAT, CHARINDEX(', ', NAME_BAT) - 1)) AS FIRST_NAME
, RTRIM(LEFT(NAME_BAT, CHARINDEX(', ', NAME_BAT) - 1)) AS LAST_NAME
, LTRIM(RIGHT(NAME_BAT, CHARINDEX(', ', NAME_BAT) - 1)) + ' ' + RTRIM(LEFT(NAME_BAT, CHARINDEX(', ', NAME_BAT) - 1)) AS NAME_FULL
FROM pitch_aggregate
;
and here is a screenshot of the output:
Output from SQL query
Why are the first four rows perfect, then row 5 includes a leading comma and space before the name, and in row 8 the first name has the first two letter cut off?
Take
LTRIM(RIGHT(NAME_BAT, CHARINDEX(', ', NAME_BAT) - 1)) AS FIRST_NAME
Presume data like Casanova, Bob
CHARINDEX(', ', NAME_BAT) returns 9
RIGHT(NAME_BAT, CHARINDEX(', ', NAME_BAT) - 1) is the rightmost 9-1 = 8 characters, which is nova, Bob
(All your sample/testing firs and last names are nearly the same length.) I'm guessing this is not what you really want?
Now, something like
SUBSTRING(NAME_BAT, CHARINDEX(', ', NAME_BAT) + 2, 100)
might be what you're looking for. Me, I see it as a prime example of why SQL is a poor place to implement string manipulations.
I have tested your query and you do indeed have some formatting issues.
Rather than pick it apart, here is a simpler working alternative you can try. By using cross apply and a values construct you can abstract out the string splitting to leave a more easy to use select list of columns.
select name_bat, f.name FirstName, l.name LastName, Concat_ws(' ',f.name,l.name) Name_full
from t
cross apply (values( Left(name_bat,CharIndex(',',name_bat)-1 )))l(name)
cross apply (values( Replace(name_bat,Concat(l.name,', '),'') ))f(name)
See original and new version example

What MySQL LIKE wildcard should I use to return someone's name without their title/prefix name?

I want to return name of customers and order them, but their titles must be excluded in ordering.
SELECT name
FROM customers
WHERE name LIKE ...
ORDER BY name
I mean by 'their titles' is such as Dr., Sn., Lady, Sir, Mr., and Mrs.
Possible solution to your problem.
In Oracle:
regexp_replace(user_name, '^(MISS|MS\.|MS|MRS\.|MRS|MR\.|MR)\s*', '') as user_name
Also you can use REPLACE () function like:
REPLACE (user_name, 'MISS', '') as user_name
If you have a column structure like (mr | mrs | other) / space / username you can try this:
with users(user_name) as
(select 'mr user name1' from dual union all
select 'miss username2 ' from dual union all
select 'other username 3' from dual )
select substr(user_name,instr(user_name,' ')+1) real_username from users
Output:
REAL_USERNAME
----------------
username 1
username 2
username 3
In MSSQL:
DECLARE #str VARCHAR(500)='Mr Sam'
SELECT Title,
first_name,
Substring(NAME, CASE
WHEN Charindex(' ', NAME) = 0 THEN 1
ELSE Charindex(' ', NAME)
END, Len(NAME)) last_name
FROM (SELECT CASE
WHEN LEFT(#str, Charindex(' ', #str)) IN( 'Mr', 'Mrs', 'Miss' ) THEN LEFT(#str, Charindex(' ', #str))
ELSE ''
END AS Title,
CASE
WHEN LEFT(#str, Charindex(' ', #str)) IN ( 'Mr', 'Mrs', 'Miss' ) THEN LEFT(Stuff(#str, 1, Charindex(' ', #str), ''), Charindex(' ', Stuff(#str, 1, Charindex(' ', #str), '')))
ELSE LEFT(#str, Charindex(' ', #str))
END AS first_name,
CASE
WHEN LEFT(#str, Charindex(' ', #str)) IN ( 'Mr', 'Mrs', 'Miss' ) THEN Stuff(#str, 1, Charindex(' ', #str), '')
ELSE #str
END NAME) a
Technically using a % before their name will allow any prefix, which would get you the desired result (ex. WHERE name LIKE ('%' + #name). However, this is not the recommended approach on larger data sets as you will see significant performance issues with this approach.
You need to be more specific. First of all: Which SQL "flavor" are you using? Postgres? Oracle? MySql? This is very important because each engine has different functions. Every time you ask an SQL question in SO, be sure to include at the very least a tag mentioning which DBMS you're using.
Now, what do you mean by "I shouldn't return them". Do you mean you should not return records which have a prefix, or do you mean you need to return the records but without the prefix? (So if you have Dr. Henry Gutierrez, do you exclude him from the result? Or have it output as Henry Gutierrez?)
This is also a good place for another tip: Always write an expected output in your questions. "If X is Y then I expect the output to be this:"
If you need to exclude them entirely, you can use a REGEXP match (Once again, I cannot list a specific function because I have no idea which type of SQL you're using) Something like WHERE REGEXP(UPPER(COL)) NOT ('^(MS|MR)\s+.*$')
If it's the 2nd case, that's going to be much harder because you'd need to get a substring which excludes the prefix, but the prefixes all have different sizes so you can't just write a "one size fits all"
In general, it's a bad normalization practice to have prefixes in your SQL database. You should have a column called PREFIX and another column for the name itself.
EDIT: Based on your answer. This is the closest you can get to achieving what you want.
SELECT NAME
FROM (SELECT NAME,
CASE WHEN NAME LIKE 'MR %' THEN SUBSTRING(NAME, 4)
WHEN NAME LIKE 'MRS %' THEN SUBSTRING(NAME, 5)
ELSE NAME AS NAME2
FROM YOUR_TABLE ORDER BY NAME2) AS SUBQ
I am 99% sure this will not return the results ordered though, because the select order might be ignored outside of the subquery, so you can also just try whats in the subquery in a main query instead, but this will output 2 columns.
***My reply is in pseudocode. It is not exactly MySql syntax, you will need to check MySql documentation for the actual substring function implementation it has and for the CASE syntax.

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

How to find more than 1 uppercase character

I'm running a series of SQL queries to find data that needs cleaning up. One of them I want to do is look for:
2 or more uppercase letters in a row
starting with a lowercase letter
space then a lowercase letter
For example my name should be "John Doe". I would want it to find "JOhn Doe" or "JOHN DOE" or "John doe", but I would not want it to find "John Doe" since that is formatted correctly.
I am using SQL Server 2008.
The key is to use a case-sensitive collation, i.e. Latin1_General_BIN*. You can then use a query with a LIKE expression like the following (SQL Fiddle demo):
select *
from foo
where name like '%[A-Z][A-Z]%' collate Latin1_General_BIN --two uppercase in a row
or name like '% [a-z]%' collate Latin1_General_BIN --space then lowercase
*As per How do I perform a case-sensitive search using LIKE?, apparently there is a "bug" in the Latin1_General_CS_AS collation where ranges like [A-Z] fail to be case sensitive. The solution is to use Latin1_General_BIN.
First, I think you should make a function that returns a proper name (sounds like you need one anyway). See here under the heading "Proper Casing a Persons Name". Then find the ones that don't match.
SELECT Id, Name, dbo.ProperCase(Name)
FROM MyTable
WHERE Name <> dbo.PoperCase(Name) collate Latin1_General_BIN
This will help you clean up the data and tweak the function to what you need.
You can use a regular expression. I'm not a SQL Server whiz, but you want to use RegexMatch. Something like this:
select columnName
from tableName
where dbo.RegexMatch( columnName,
N'[A-Z]\W[A-Z]' ) = 1
If your goal is to update your column to capitalize the first character of each word (in your case firstName and lastName) , you can use the following query.
Create a sample table with data
Declare #t table (Id int IDENTITY(1,1),Name varchar(50))
insert into #t (name)values ('john doe'),('lohn foe'),('tohnytty noe'),('gohnsdf fgedsfsdf')
Update query
UPDATE #t
SET name = UPPER(LEFT(SUBSTRING(Name, 1, CHARINDEX(' ', Name) - 1), 1)) + RIGHT(SUBSTRING(Name, 1, CHARINDEX(' ', Name) - 1), LEN(SUBSTRING(Name, 1, CHARINDEX(' ', Name) - 1)) - 1) +
' ' +
UPPER(LEFT(SUBSTRING(Name, CHARINDEX(' ', Name) + 1, 8000), 1)) + RIGHT(SUBSTRING(Name, CHARINDEX(' ', Name) + 1, 8000), LEN(SUBSTRING(Name, CHARINDEX(' ', Name) + 1, 8000)) - 1)
FROM #t
Output
SELECT * FROM #t
Id Name
1 John Doe
2 Lohn Foe
3 Tohnytty Noe
4 Gohnsdf Fgedsfsdf
I use this way:
;WITH yourTable AS(
SELECT 'John Doe' As name
UNION ALL SELECT 'JOhn Doe'
UNION ALL SELECT 'JOHN DOE'
UNION ALL SELECT 'John doe'
UNION ALL SELECT 'John DoE'
UNION ALL SELECT 'john Doe'
UNION ALL SELECT 'jOhn dOe'
UNION ALL SELECT 'jOHN dOE'
UNION ALL SELECT 'john doe'
)
SELECT name
FROM (
SELECT name,
LOWER(PARSENAME(REPLACE(name, ' ', '.'), 1)) part2,
LOWER(PARSENAME(REPLACE(name, ' ', '.'), 2)) part1
FROM yourTable) t
WHERE name COLLATE Latin1_General_BIN = UPPER(LEFT(part1,1)) + RIGHT(part1, LEN(part1) -1) +
' ' + UPPER(LEFT(part2,1)) + RIGHT(part2, LEN(part2) -1)
Note:
This will be good for just two parted names for more, it should improved.

SQL- Get the substring after first space and second space in separate columns

I have a column as FullName containg FirstName, MiddleName, LastName in it.
For example:
FullName: Marilyn Kean Kirkland
I want to have 3 separate columns for FirstName, MiddleName and LastName from the FullName by taking a substring from it.
I am pulling the FirstName by using the code:
substring(c.LegalName, 1, CHARINDEX(' ', c.LegalName)) as 'First Name'
I am wondering how can I pull just the middle name which comes after first space and before second space?
Also, I want to pull the last name which comes after the second space?
SQL Server doesn't have very good string manipulation functions. This is easier with subqueries:
select firstname,
stuff(reverse(stuff(reverse(legalname), 1, len(lastname) + 1, '')),
1, len(firstname) + 1, '')
from (select legalname,
left(legalname, charindex(' ', legalname) - 1) as firstname,
right(legalname, charindex(' ', reverse(legalname)) - 1) as lastname
. . .
) c
However, I would be very careful, because not all people have three part names. And others have suffixes (JR, SR) and other complications.
You can try something like this.
;WITH c AS
(
SELECT 'Marilyn Kean Kirkland' AS legalname
UNION ALL SELECT 'J Smith' AS legalname
)
SELECT
SUBSTRING(legalname,1,space1) firstname,
SUBSTRING(legalname,space1,space2 - space1 + 1) middlename,
SUBSTRING(legalname,space2 + 1,totallength - space2) lastname
FROM
(
SELECT
legalname,
CHARINDEX(' ',legalname) space1,
LEN(legalname) - CHARINDEX(' ',REVERSE(legalname)) space2,
LEN(legalname) as totallength
FROM c
)c
GO
As noted above by other users as well,these scripts will work with user that only have 3 part or 2 part names.