SQL Substring Functions - sql

I have a column named full name. I want to split them into two columns, first name and last name.
I am having a trouble with a persons with two first names. If the first name encounters a space it was considered last name.
I want this:
Full name : John Michael Smith
Firstname: John Michael
Lastname: Smith
However, I am getting:
Firstname: John
Lastname: Michael Smith

Try:
declare #n varchar(max) = 'John Michael Smith'
select REVERSE(SUBSTRING(REVERSE(#n), CHARINDEX(' ', REVERSE(#n)), 100)) FirstName

Check the below link:
SQL SERVER – Reverse String Word By Word – Part 2

You can split the string by checking for the index of last space and using it with LEFT and RIGHT function.
DECLARE #name varchar(100)= 'John Michael Smith'
SELECT LEFT(#name,LEN(#name)-CHARINDEX(' ',REVERSE(#name))) AS [Firstname],RIGHT(#name,CHARINDEX(' ',REVERSE(#name))) AS [LastName]

--Create table from below script
create table users(id int IDENTITY(1,1) PRIMARY KEY, name varchar(50));
--Insert Record for query for testing
insert into users(name)
values('John Abraham'),
('John Mark Abraham'),
('John Vens Abraham'),
('John Abraham');
--Run below query for getting all inserted records.
select * from users;
--Run below query for getting first and last name from name
select id , name, SUBSTRING(name,0, CHARINDEX(last_name,name)) as first_name, last_name from
(
select id, name, REVERSE(SUBSTRING(REVERSE(name),0,CHARINDEX(' ',REVERSE(name)))) as last_name from users
) as A

You can hi-jack 'parsename'. This only works up to 4 intervals but a nice option;
declare #name varchar(100)
set #name='John Michael Smith'
select PARSENAME(REPLACE(#name,' ','.'),1) -- returns Smith
select PARSENAME(REPLACE(#name,' ','.'),2) -- returns Micheal
select PARSENAME(REPLACE(#name,' ','.'),3) -- Returns John
select PARSENAME(REPLACE(#name,' ','.'),4) -- returns NULL

Related

select first_name,length(trim(FIRST_NAME)) as lengthOfName_without_space from employees;

i have first name as 'jose manuel' in my database- its total character length is 11 (combining space)
when i run the above query it is showing me output as 11.
but i need output without space i mean after trimming space ie., 10.
how do i do that in sql.
I'm looking through the comments, and The Impaler is correct.
In this circumstance, using Replace would help you a lot.
I've included testing data into a temporary table.
You can just use the select part without the stuff above that, just change the from part.
Declare #TestData TABLE
(
FIRST_NAME varchar(24)
);
INSERT INTO #TestData (FIRST_NAME) select 'jose manuel'
INSERT INTO #TestData (FIRST_NAME) select 'bob chris'
INSERT INTO #TestData (FIRST_NAME) select 'steven'
select t1.FIRST_NAME,
len(t1.FIRST_NAME) as 'Original_Length',
len( replace(t1.FIRST_NAME, ' ', '') ) as 'New_Length'
from #TestData as t1
The result of this will give you:
FIRST_NAME
Original_length
New_length
jose manuel
11
10
bob chris
9
8
steven
6
6

Function to check for NULL and concatenating the strings

I have a SQL statement that concatenates First Name and Last Name of the person. I use the following SQL statement.
ISNULL(FullName.FirstName, '') + ' ' + ISNULL(FullName.LastName, '')
What I need is to change this to add the FirstName and LastName only if they are not both NULL. If one of them is not NULL, use that value.
Examples:
FirstName and LastName are NULL -> NULL
FirstName is John and LastName is NULL -> John
FirstName is NULL and LastName is Doe -> Doe
-> indicates the result
Use CONCAT() to concatenate without any NULL issues
TRIM() to remove any spaces for when one or both fields are missing
NULLIF() to replace '' with NULL if first and last name are both
missing
SQL Server 2017+ Solution
DROP TABLE IF EXISTS #emp
CREATE TABLE #emp (ID INT IDENTITY(1,1), FirstName VARCHAR(25), LastName VARCHAR(25));
INSERT INTO #emp
VALUES(null,null)
,('John',null)
,('Doe',null)
,('John', 'Doe');
SELECT FullName = NULLIF(TRIM(CONCAT(FirstName,' ',LastName)),'')
,*
FROM #emp
Actually if you just wrap you current expression inside TRIM() it should give you the behavior you want:
SELECT TRIM(ISNULL(FullName.FirstName, '') + ' ' +
ISNULL(FullName.LastName, '')) AS FullName
FROM yourTable;
In the event that only the first or last name be present, your original expression would leave a dangling leading/trailing space. The call to TRIM() fixes that by removing this extra space.
You can use simple case statement to solve this:
create table emp (emp_id int4, fname varchar(10), lname varchar(10));
insert into emp (emp_id) values(1);
insert into emp (emp_id,fname) values(2, 'John');
insert into emp (emp_id,lname) values(3, 'Doe');
insert into emp (emp_id,fname,lname) values(4, 'John', 'Doe');
select emp_id,fname, lname,
case
WHEN FNAME is not null and LNAME is not null then
FNAME||' '||LNAME
WHEN FNAME is not null and LNAME is NULL then
FNAME
WHEN FNAME is null and LNAME is not NULL then
LNAME
else null
end as FULL_NAME
from emp;
A better SQL Server 2017 solution:
Use the new CONCAT_WS function, which concatenates with a separator, ignoring nulls
CREATE TABLE #emp (ID INT IDENTITY(1,1), FirstName VARCHAR(25), LastName VARCHAR(25));
INSERT INTO #emp
VALUES(null,null)
,('John',null)
,('Doe',null)
,('John', 'Doe');
SELECT FullName = CONCAT_WS(' ', FirstName, LastName)
,*
FROM #emp;
db<>fiddle

How can I find a string separated by a space in SQL

I am trying to find a way where I can skim out records of customers where 'First Name' and 'Middle Name' has been entered in the first_name column in the customer detail table. For examples
first_name, Last_name, mobile_no
Mary Jane Smith 0400000000
Shane Angus John 0400000000
Rudy Gill 0401111111
Rachel Rose
from the above examples I only want to find records
Mary Jane Smith 0400000000
Shane Angus John 0400000000
You can use like:
select t.*
from t
where first_name like '% %';
Note: This just checks for a space. It does not guarantee that one of the names is a middle name.
here's another solution for you if you want to get more complex and account for the middle name.
create table test (first_name nvarchar(50), middle_name nvarchar(50), last_name nvarchar(75), mobile_no nvarchar(10))
insert test
select 'mary jane', null, 'smith', '0400000000'
union all
select 'shane angus', null, 'john', '0400000000'
union all
select 'rudy', 'jacob', 'gill', '0401111111'
union all
select 'rachel', 'liza', 'rose', '0400000000'
select *
from test
where middle_name is null and charindex(char(32),first_name) > 0
this won't help you though if the first name is double-worded like Bobby Jo hence the middle name check.

SQL Server STRING_SPLIT()

I'm trying to use this function on a column but it seems that that is not allowed:
If I use
SELECT *
FROM STRING_SPLIT('John,Jeremy,Jack', ',')
I get the values 'John', 'Jeremy and 'Jack'
Whilst if I use:
SELECT *
FROM STRING_SPLIT(Obs, ' ')
(Obs is text)
or
SELECT *
FROM STRING_SPLIT(appointments notes, ' ')
I get the error message:
Argument data type void type is invalid for argument 1 of string_split function
I even tried:
SELECT *
FROM STRING_SPLIT(select obs from log, '-')
which results in this error:
Incorrect syntax near the keyword 'select'.
Msg 102, Level 15, State 1, Line 6
Incorrect syntax near '-'
How can I solve this issue?
When you are using string_split() on a column of a table you can try it with cross apply.
Here goes your query:
select value from
log cross apply STRING_SPLIT(obs,',')
DB-Fiddle
your query:
create table log(Obs varchar(500));
insert into log values('ohn,Jeremy,Jack');
Your query:
select value from
log cross apply STRING_SPLIT(obs,',')
Output:
value
ohn
Jeremy
Jack
example:
CREATE TABLE contacts (
id INT PRIMARY KEY IDENTITY,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
phones VARCHAR(500)
);
INSERT INTO
contacts(first_name, last_name, phones)
VALUES
('John','Doe','(408)-123-3456,(408)-123-3457'),
('Jane','Doe','(408)-987-4321,(408)-987-4322,(408)-987-4323');
Query:
SELECT
first_name,
last_name,
value phone
FROM
contacts
CROSS APPLY STRING_SPLIT(phones, ',');
Output:
first_name
last_name
phone
John
Doe
(408)-123-3456
John
Doe
(408)-123-3457
Jane
Doe
(408)-987-4321
Jane
Doe
(408)-987-4322
Jane
Doe
(408)-987-4323
db<fiddle here
Thank you all for the help, I've tried your suggestions but keep getting the same errors.
Here is a 2 record sample from the log column:
Obs
ID:786988|Patient_ID:320165|Staff_ID:PF|Date:05/06/2021 13:00:24|DiaryTemplates_ID:244799|Notes:Relatório 786988|Access:1|EventID:5|Status:4|Staff_ID_Writer:PES|Staff_ID_Signature:0|StatusReason:|StatusObs:|DateReceived:05/06/2021 13:00:24|NameReceived:|CountPrints:0|Staff_ID_Auxiliar:PES|PatientEpisode_ID:664831|
ID:872474|Patient_ID:340246|Staff_ID:PFI|AppointmentDate:29/05/2021 09:33:21|Convencao:XCD_ttt_NE_C2|NBenef:3X34977|NRequisicao:4SFR09995393153409|NAutorization:|Treatment_ID:6898|TreatmentCode:743.9|TotalValue:75,34|PatientValue:0,00|ConvencaoValue:75,34|StaffValue:0,00|FactConvencao:True|FactConvencaoDate:31/05/2021 19:14:53|FactStaff:False|FactStaffGuID:|PatientValueDiscount:0,00|Recibo:True|ReciboGuID:|FactConvencaoClinic_ID:HJUSD2|Piece:|ClinicsLocations_ID:1|FactConvencaoYearMonth:202105|FactConvencaoSequencial:31|FactConvencaoLote:155|FactConvencaoStaff_ID:TRI|Quantity:1|FactConvencaoLoteType:M|RequesterCode_Medico:M2XD33|RequesterCode_CentroSaude:XCD202|PatientDiary_ID:F45724|Appointment_ID:793049|DataExecucao:29/05/2021 09:30:00|DataEntrega:04/06/2021 00:00:00|PatientEpisode_ID:664807|ToExecute:True|Position:1|FactConvencaoNDevolucao:|FactConvencaoCanDefact:|NRequisicaoDate:|DataFacturacao:29/05/2021 09:33:21|ClinicalReportsDestinations_ID:|ClinicalReportsDestinations_ByWho:|ClinicalReportsDestinations_Date:|ClinicalReportsDestinations_DateDelivery:|TypeOrigem:|SPMS_IdMcdt:|
Each of the strings between '|' and ':' is a column name for another table, with its value after the ':'. The data type is 'text'.
I need to split those values into separate columns to update the other table.
Thanks.

Inserting multiple names in same cell with separated commas

Previously, I was trying to keep ALL previous last names of an employee in a table cell with commas (see below) but I didn’t know how. Someone then suggested using normalization which I’m not sure if it’ll be easier in this situation. My boss wants to display all previous last names of an employee on a web page each time she edits her account info. Simply put, when Judy changes her last name again – her last name Kingsley should be inserted behind Smith. So, my question is back to whether or not it is possible to add multiple last names in the same cell, separated with commas as I thought it’ll be simpler when I use a variable on the web page to display all the Alias at once? Yet, I’ve no clue the complexity to write the codes for this. Any help is truly appreciated.
Current SQL table
+---------------+-----------------+----------------+--------------------+
People FirstName LastName Alias
+---------------+-----------------+----------------+--------------------+
002112 Judy Smith Hall
Preferred
+---------------+-----------------+----------------+--------------------+
People FirstName LastName Alias
+---------------+-----------------+----------------+--------------------+
002112 Judy Kingsley Hall, Smith
Keep the database normalized.
People:
(Id, Firstname, Lastname)
LastnameHistory:
(PeopleId, OldLastname, NewLastname, DateChanged)
You can the create a view which would be a "GROUP_CONCAT" type of query to transform the data as required.
An example:
DECLARE #people TABLE ( id INT IDENTITY(1,1), fname VARCHAR(50), lname VARCHAR(50))
DECLARE #lnameHistory TABLE ( id INT IDENTITY(1,1), people_id INT, lname VARCHAR(50), date_changed DATETIME)
INSERT INTO #people (fname, lname)
VALUES ('john', 'smith'), ('jane', 'doe')
INSERT INTO #lnameHistory (people_id, lname, date_changed)
VALUES (2, 'shakespeare', '2012-01-01'), (2, 'einstein', '2013-12-12')
;WITH group_concat AS
(
SELECT people_id, LEFT(lnames , LEN(lnames )-1) AS lnames
FROM #lnameHistory AS o
CROSS APPLY
(
SELECT lname + ', '
FROM #lnameHistory AS i
WHERE o.people_id = i.people_id
ORDER BY date_changed ASC
FOR XML PATH('')
) pre_trimmed (lnames)
GROUP BY people_id, lnames
)
SELECT p.*, gc.lnames FROM #people p
JOIN group_concat gc ON gc.people_id = p.id
Some reference for syntax:
SQL Server CROSS APPLY and OUTER APPLY
XML Data (SQL Server)
Assuming your update statement is a stored procedure taking in parameters of #personId and #newLastName:
EDIT
Sorry, wrong version of SQL. Have to do it the old school way!
UPDATE PeopleTable
SET Alias = Alias + ', ' + LastName,
LastName = #newLastName
WHERE
People = #personId
When you update the table for a new LastName, use something like this:
UPDATE <table> SET Alias = Alias + ', ' + LastName, LastName = <newLastName>