Update using case in two fields - sql

I need to use the query below in an update in order to update the first and last name. What's the best option to do that?
SELECT
person.fullName,
(CASE WHEN 0 = CHARINDEX(' ', person.fullName)
then person.fullName
ELSE SUBSTRING(person.fullName, 1, CHARINDEX(' ', person.fullName)) end) as first_name,
(CASE WHEN 0 = CHARINDEX(' ', person.fullName)
THEN ''
ELSE SUBSTRING(person.fullName,CHARINDEX(' ', person.fullName), LEN(person.fullName) )end) last_name
FROM person
Thank you.

Please Try this code, i did not modify your condition , but showing you the logic to use your code to update first and last name. I assume the table has FirstName and LastName columns
UPDATE Person
SET
Person.FirstName =
(CASE WHEN 0 = CHARINDEX(' ', person.fullName)
then person.fullName
ELSE SUBSTRING(person.fullName, 1, CHARINDEX(' ', person.fullName)) end) ,
Person.LastName =
(CASE WHEN 0 = CHARINDEX(' ', person.fullName)
THEN ''
ELSE SUBSTRING(person.fullName,CHARINDEX(' ', person.fullName), LEN(person.fullName) )end)
FROM person

Related

How to Split the address string, House number and Street Name using SQL?

I'm trying to separate the house number and street name from an address.
I'm able to split most of the addresses until I get to an address that contains Numbers and letters as part of the HouseNumber.
I have tried below and it works for most part. But it doesn't work for an address like 876A Mountain Breeze Rd. I'm unable to split the House Number 876A from rest of the address.
Is their a way to split the 876A As the [House Number]?
SELECT
C.CustomerID
,CASE
WHEN ISNUMERIC(LEFT(LTRIM(C.ServiceAddress), CHARINDEX(' ',
LTRIM(C.ServiceAddress)))) = 1 THEN
LEFT(LTRIM(C.ServiceAddress), CHARINDEX(' ',
LTRIM(C.ServiceAddress)))
ELSE
NULL
END AS [House Number]
,CASE
WHEN ISNUMERIC(LEFT(LTRIM(C.ServiceAddress), CHARINDEX(' ', LTRIM(C.ServiceAddress)))) = 1 THEN
LTRIM(RTRIM(SUBSTRING(
LTRIM(C.ServiceAddress),
CHARINDEX(' ', LTRIM(C.ServiceAddress)) + 1,
LEN(LTRIM(C.ServiceAddress)))))
ELSE
LTRIM(RTRIM(C.ServiceAddress))
END AS [Street Name]
FROM dbo.Customers AS C
Can you try this and see if its giving you correct results?
SELECT
C.CustomerID
,CASE
WHEN ISNUMERIC(LEFT(LTRIM(C.ServiceAddress), CHARINDEX(' ',
LTRIM(C.ServiceAddress)))) = 1 OR ISNUMERIC(LEFT(LTRIM(C.ServiceAddress), CHARINDEX('
',
LTRIM(C.ServiceAddress)))) = 0 THEN
LEFT(LTRIM(C.ServiceAddress), CHARINDEX(' ',
LTRIM(C.ServiceAddress)))
ELSE
NULL
END AS [House Number]
,CASE
WHEN ISNUMERIC(LEFT(LTRIM(C.ServiceAddress), CHARINDEX(' ',
LTRIM(C.ServiceAddress)))) = 1 OR ISNUMERIC(LEFT(LTRIM(C.ServiceAddress), CHARINDEX('
', LTRIM(C.ServiceAddress)))) = 0 THEN
LTRIM(RTRIM(SUBSTRING(
LTRIM(C.ServiceAddress),
CHARINDEX(' ', LTRIM(C.ServiceAddress)) + 1,
LEN(LTRIM(C.ServiceAddress)))))
ELSE
LTRIM(RTRIM(C.ServiceAddress))
END AS [Street Name]
FROM dbo.Customers AS C

Extract forename if the character is more then 2 letter

I have to get the forename from the c.forename if c.known_as column is null or blank.
This i achieved with case when statement using
CASE
WHEN IND.KNOWN_AS IS NULL OR ind.KNOWN_AS=''
THEN ind.FORENAMES
ELSE ind.KNOWN_AS
END AS 'Known As'
My issue is in the forename column i have name like Jhon Smith where i would like to extract only John, below is an example what i want to achieve
Desire output c.forename
John Mr John
Jhon Jhon Smith
blank Jo
blank J
So , basically it will only take forname skipping 'Mr', 2nd it should take only forename which has more than 2 character.
My current query is:
Select ind.FORENAMES,
ind.KNOWN_AS,
case when (known_as is null or known_as = '' ) and charindex(' ', forenames) > 2
then substring(forenames, 1, charindex(' ', forenames) - 1) end as FORENAMES2,
output
from individual ind
join member m on m.individual_ref=ind.individual_ref
and m.MEMBERSHIP_NO in ('001','002','003','004','005','006','007')
where m.member_status=33
You could use following case when statement to verify your conditions:
For SQL Server:
case when (c.known_as is null or c.known_as = '' )
and charindex(' ', c.forename) > 3 then substring(c.forename, 1, charindex(' ', c.forename) - 1) end
For MySQL:
case when (c.known_as is null or c.known_as = '' )
and locate(' ', c.forename) > 3 then substring(c.forename, 1, locate(' ', c.forename) - 1) end
Little explanation: if the first name must be longer than 2 characters, that means that first space must occur at least at index 4. And that what the condition is about: locate(' ', c.forename) > 3 or substring(' ', c.forename) > 3
NOTE
You have to first strip down all occurences of Mr, Mrs, Ms in c.forename column, like this (syntax for MySQL and SQL Server):
replace(replace(replace(c.forename, 'Mrs ', ''), 'Mr ', ''), 'Ms ', '')
You have to include it in your query lke this:
Select FORENAMES,
KNOWN_AS,
case when (known_as is null or known_as = '' ) and charindex(' ', FORENAMES2) > 2
then substring(FORENAMES2, 1, charindex(' ', FORENAMES2) - 1) end as FORENAMES2,
output
from (
Select ind.FORENAMES,
ind.KNOWN_AS,
replace(replace(replace(ind.FORENAMES, 'Mrs ', ''), 'Mr ', ''), 'Ms ', '') FORENAMES2,
output
from individual ind
join member m on m.individual_ref = ind.individual_ref
where m.member_status=33
and m.MEMBERSHIP_NO in ('001','002','003','004','005','006','007')
)
Try this:
DECLARE #DataSource TABLE
(
[name] VARCHAR(32)
);
INSERT INTO #DataSource ([name])
VALUES (' Mr John ')
,('Jhon Smith')
,(' Jo ')
,(' J ');
WITH SanitizeDataSoruce ([name], [name_reversed]) AS
(
SELECT LTRIM(RTRIM([name]))
,REVERSE(LTRIM(RTRIM([name])))
FROM #DataSource
)
SELECT [name]
,CASE
WHEN CHARINDEX(' ', [name]) > 1 THEN REVERSE(SUBSTRING([name_reversed], 0, CHARINDEX(' ', [name_reversed])))
ELSE ''
END
FROM SanitizeDataSoruce;

SQL count string matches in each row

Please take a look at this simple SQL server database :
What I want is, I want to create a summary with only 3 column, here is the code:
select ProductID, Name,
*code* as CountString
from product
where Name in ('this', 'is', 'count', 'example')
I want the result to have 3 column, and the column "CountString" is the total number of string that matches ('this','is', 'count', 'example'). Here is the result I want :
So for example, I want the Countstring for ProductID 1 is 4, because it contains all of 4 words.
If you can solve this, it would be amazing!
If I understand correctly:
select ProductID, Name,
( (case when Name like '%this%' then 1 else 0 end) +
(case when Name like '%is%' then 1 else 0 end) +
(case when Name like '%count%' then 1 else 0 end) +
(case when Name like '%example%' then 1 else 0 end)
) as CountString
from product;
Note: Any Name that has "this" also has "is".
If "words" are separated by spaces (and only spaces), you can do:
select ProductID, Name,
( (case when concat(' ', Name, ' ') like '% this %' then 1 else 0 end) +
(case when concat(' ', Name, ' ') like '% is %' then 1 else 0 end) +
(case when concat(' ', Name, ' ') like '% count %' then 1 else 0 end) +
(case when concat(' ', Name, ' ') like '% example %' then 1 else 0 end)
) as CountString
from product;
The following query should suffice your need ---
SELECT PRODUCTID,
NAME,
REGEXP_COUNT(NAME, 'this|is|count|example', 1, 'c') CountString
FROM product;
This query will result in "Case Sensitive" checking, means only "example" will be counted not "Example". If you want "Case Insensitive" checking just put 'i' instead of 'c'.

Error: invalid length parameter passed to the right function in name parsing script

I gotta problem. When I run the below code I get an error saying:
invalid length parameter passed to the right function. What does that mean and how can it go away? Its to parse a name like smith, steve s to steve r smith in columns firstname, middlename and lastname
UPDATE table5
SET lastName = LEFT(Name, CHARINDEX(', ', Name) - 1),
firstname = SUBSTRING(Name,
CHARINDEX(', ', Name) + 2,
CASE
WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name) + 1
ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2)
END - CHARINDEX(', ', Name) - 2
),
middlename= RIGHT(Name,
LEN(Name) - CASE
WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name)
ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2)
END
)
the "name" column is varchar (50) and firstname, middlename and lastname columns are also set to varchar (50) . I'm kinda stumped.. thanks in advance
The error is because CHARINDEX() is returning 0 and SUBSTRING() require at number bigger than 0. Your assumption is correct string without middle name will give you error.
Can you check this fiddle and let me know if that is the format you are using for name. Because the Gordon Linoff query seem to be working for select
SQL FIDDLE
NOTE:
I update the SqlFiddle with
WHERE CHARINDEX(', ', Name) > 0
My guess is some of your name doesnt have ,
You can validate doing
SELECT Name
FROM test
WHERE CHARINDEX(', ', Name) = 0
You can also check your other CHARINDEX condition with your data to see which one RETURN 0
I would prefer to write a function, Here is the code.
IF object_id(N'udf_NameSplitter', N'FN') IS NOT NULL
DROP FUNCTION udf_NameSplitter
GO
CREATE FUNCTION udf_NameSplitter
(
#FullName VARCHAR(50),
#NameSplitCharacter CHAR(1),
#NamePart CHAR(50) /*FN-firstname,MN-middlName,LN-lastName*/
)
RETURNS VARCHAR(50)
AS
BEGIN
DECLARE #StartIndex INT, #EndIndex INT, #NameTblString VARCHAR(50)
DECLARE #NameTbl TABLE (ID INT Identity(1,1),Item NVARCHAR(1000))
SET #StartIndex = 1
IF SUBSTRING(#FullName, LEN(#FullName) - 1, LEN(#FullName)) <> #NameSplitCharacter
BEGIN
SET #FullName = #FullName + #NameSplitCharacter
END
WHILE CHARINDEX(#NameSplitCharacter, #FullName) > 0
BEGIN
SET #EndIndex = CHARINDEX(#NameSplitCharacter, #FullName)
INSERT INTO #NameTbl(Item)
SELECT SUBSTRING(#FullName, #StartIndex, #EndIndex - 1)
SET #FullName = SUBSTRING(#FullName, #EndIndex + 1, LEN(#FullName))
END
SELECT #NameTblString = LTRIM(RTRIM(Item))
FROM #NameTbl
WHERE ID = CASE WHEN #NamePart = 'LN' THEN 1 WHEN #NamePart = 'FN' THEN 2 ELSE 3 END
RETURN (#NameTblString)
END
GO
Test the function with a few scenarios. I think I covered most but its worth having a second look. I would highly recommend doing a select before an update and see if the data is accurate or as expected.
DECLARE #Name VARCHAR(50) = 'lastName , firstname ,middleName '
SELECT
lastName=dbo.udf_NameSplitter(#Name,',','LN'),
firstname=dbo.udf_NameSplitter(#Name,',','FN'),
middleName=dbo.udf_NameSplitter(#Name,',','MN')
Usage with your table
UPDATE table5
SET lastName=LEFT(Name, CHARINDEX(', ', Name) - 1),
firstname=SUBSTRING(Name, CHARINDEX(', ', Name) + 2, CASE WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name) + 1 ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) END - CHARINDEX(', ', Name) - 2),
middlename=RIGHT(Name, LEN(Name) - CASE WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name) ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) END)
It means that charindex() is returning 0, which you are passing to another function. One way to fix this is:
UPDATE table5
SET lastName=LEFT(Name, CHARINDEX(', ', Name) - 1),
firstname=SUBSTRING(Name, CHARINDEX(', ', Name) + 2, CASE WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name) + 1 ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) END - CHARINDEX(', ', Name) - 2),
middlename=RIGHT(Name, LEN(Name) - CASE WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name) ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) END)
WHERE Name LIKE '% % %';
This ensures that Name has two spaces, which your logic is assuming.
select left(RTRIM(ltrim(C_Subarea_Code)),2) +
right(RTRIM(ltrim(C_Subarea_Code)),len(RTRIM(ltrim(C_Subarea_Code)))-3)
from Tbl_Doc_Stock_Chem_Add_Mst
in sql

parsing first and last name from fullname column

Below is the data I am trying to manipulate. I am trying to get the last name and first name before the second comma
This is the code I currently have:
SELECT
[SDN_Name],
CASE WHEN CHARINDEX(', ', [SDN_Name]) > 0 THEN
LEFT([SDN_Name],(CHARINDEX(', ',[SDN_Name],1)-1))
ELSE
[SDN_Name]
END as LName,
CASE WHEN CHARINDEX(', ', [SDN_Name]) > 0 THEN
SUBSTRING([SDN_Name],CHARINDEX(', ',[SDN_Name])+1, ( LEN([SDN_Name]) - CHARINDEX(', ',[SDN_Name])+1))
ELSE
NULL
END as FName
FROM [Staging].[OFAC].[TP1]
Where ([SDN_Type] = 'individual')
For instance, if the full name is DELOS REYES, Feliciano , Jr.
I want DELOS REYES as the LName
and Feliciano Semborio as the Fname
but I don't want to capture ", Jr."
I'm able to parse the last name and everything right of the first comma.
How do I write a CASEstatment that will capture the first name without the suffix of the name?
Those are commas in SDN_Name field, right? Just use the CharIndex of ', ' instead of ' ', and it should work. Like this:
SELECT [SDN_Name],
CASE WHEN CHARINDEX(', ', [SDN_Name]) > 0 THEN
LEFT([SDN_Name],CHARINDEX(', ',[SDN_Name])-1)
ELSE
[SDN_Name]
END as LName,
CASE WHEN CHARINDEX(', ', [SDN_Name]) > 0 THEN
SUBSTRING([SDN_Name], CHARINDEX(', ',[SDN_Name])+2,
CASE WHEN RIGHT([SDN_Name], 1) = '.' THEN LEN([SDN_Name]-2) ELSE LEN([SDN_Name]) END
- (2+CHARINDEX(', ',[SDN_NAME],1))
)
ELSE
NULL
END as FName