I want to transform the values of a column in my table which is supposed to contain only numbers. It is the "TEL" column.
This column currently has special characters and spaces. I need to filter this.
The additional constraint is that if the very first character (only the first character) is a "+" I would have to transform the + into "00"
You will find below an example of what is expected.
Could you please help me to create such a query?
CREATE TABLE PersonsInitial (
tel varchar(255),
firstname varchar(255),
lastname varchar(255)
);
insert into PersonsInitial(tel,firstname,lastname) values
('+41/ jfakl2 eaf3efa54844','Manu','Johns'),
('01-afe fa-e8fa5a +e5+ e+234','Fernand','Wajk'),
(' +41/34 jfakl2 eaf3efa54844','Fred','Johns')
;
select tel, firstname, lastname from PersonsInitial
--if there is a person with the same tel number chose the customer id with 'C'
--if I don't have the choice add the customer without C
CREATE TABLE PersonsFinal (
tel varchar(255),
firstname varchar(255),
lastname varchar(255))
;
insert into PersonsFinal(tel,firstname,lastname) values
('00412354844','Manu','Johns'),
('01855234','Fernand','Wajk'),
('0041342354844','Fred','Johns')
;
select tel, firstname, lastname from PersonsFinal
Example
You can add a User-Defined Function for this.
For example:
CREATE FUNCTION dbo.fnCleanTel (#Input VARCHAR(255))
RETURNS VARCHAR(255)
AS
BEGIN
DECLARE #Output VARCHAR(255) = LTRIM(RTRIM(#Input));
IF LEFT(#Output, 1) = '+'
SET #Output = STUFF(#Output,1,1,'00');
WHILE PATINDEX('%[^0-9]%', #Output) > 0
SET #Output = REPLACE(#Output, SUBSTRING(#Output,PATINDEX('%[^0-9]%',#Output),1),'');
RETURN #Output;
END;
CREATE TABLE PersonsFinal (
tel varchar(255),
firstname varchar(255),
lastname varchar(255)
);
insert into PersonsFinal (tel, firstname, lastname)
select dbo.fnCleanTel(tel) as clean_tel, firstname, lastname
from PersonsInitial;
select tel, firstname, lastname from PersonsFinal
tel | firstname | lastname
:------------ | :-------- | :-------
00412354844 | Manu | Johns
01855234 | Fernand | Wajk
0041342354844 | Fred | Johns
db<>fiddle here
This is something that translate is useful for. You can define a string of characters to remove and replace them all with a single character also to be removed, eg a space, with some additional logic for your initial 00 criteria:
declare #replace varchar(30)='abcdefghijklmnopqrstuvwxyz/+-';
select *,
Replace(Translate(Iif(Left(Replace(tel,' ',''),1)='+',Concat('00',tel),tel), #replace, Replicate(' ',Len(#replace))),' ','')
from PersonsInitial;
You can then use an Updatable CTE to fix the original data, see example in Amended DBFiddle
I'd suggest once you have fixed your data you use a Check Constraint to ensure only valid data can be used.
Related
How can I create a function that will accept 4 parameters (firstname, middlename, lastname and birthday) and return generated id coming from initial of first name, last 2 letters
of your middle name, and initial of your last name together with the year of your birthday
DELIMITER $$
CREATE FUNCTION Generated_ID (FirstName VARCHAR(255), MiddleName VARCHAR(255), LastName VARCHAR(255), Birhtday DATE)
RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
RETURN (SELECT CONCAT(LEFT(FirstName,1),RIGHT(MiddleName,2),LEFT(LastName,1),YEAR(Birthday)));
END; $$
DELIMITER ;
SELECT FirstName, MiddleName, LastName, functionName(FirstName,MiddleName,LastName,Birthday) as Generated_ID FROM FullName;
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
I'm currently developing a report in SQL Server. Let's say I have 3 columns.
FirstName | LastName | URL's
----------+----------+------------------------------------------------
Tiffany | Smith | www.example.com/accountname=%3Dtiffany%7Lsmith
The format of the URL will always be:
www.example.com/accountname=%3Dname%7Lname
How would I populate the URL column with values from FirstName and LastName like the example above?
Using concatenate:
create table #temp
(
firstname varchar(50),
lastname varchar(50)
)
insert into #temp (firstname, lastname) values
('tiffany', 'smith'),
('john', 'doe')
select
firstname
, lastname
, concat('www.example.com/accountname=%3D', firstname, '%7L', lastname) as 'url'
from #temp
You could do something like this
declare #firstname varchar(10) = 'hello'
declare #lastname varchar(10) = 'there'
select 'www.example.com/accountname=%3D'+#firstname+'%7L'+#lastname as url
the URL that is return is this
www.example.com/accountname=%3Dhello%7Lthere
simply replace the variables with your column names
;With cte(FirstName , LastName , [URL's])
AS
(
SELECT 'Tiffany', 'Smith', 'www.example.com/accountname=%3D%7L' Union all
SELECT 'john', 'doe',Null
)
SELECT FirstName
,LastName
,ISNULL(STUFF(STUFF([URL's], CHARINDEX('%3D', [URL's]) + 3, 0, FirstName),
CHARINDEX('%7L', STUFF([URL's], CHARINDEX('%3D', [URL's]) + 3, 0, FirstName)),
LEN(LastName), '%7L' + LastName), 'NA') AS [URL's]
FROM cte
OutPut
FirstName LastName [URL's]
---------------------------------------------------------------------
Tiffany Smith www.example.com/accountname=%3DTiffany%7LSmith
john doe NA
I have to update the data of one of my SQL Server table that was mistakenly updated, and this caused data of one row's cell to over-write the next. Following is an example of what the table should have been in correct state:
FirstName LastName EmailID
--------------------------------------------------
abc xyz abc.xyz#something.com
def 321 def.321#something.com
ghi 123 ghi.123#something.com
Mistakenly the data has become:
FirstName LastName EmailID
---------------------------------------------
abc xyz something
def 321 abc.xyz#something.com
ghi 123 def.321#something.com
I know that the last one record will not be found but atleast other should be restored correctly
assuming your table is ordered by firstName, lastName you can use this:
declare #contact as table (firstName varchar(255), lastName varchar(255), emailID varchar(255))
insert into #contact (firstName, lastName, emailID)
values
('abc', 'xyz', 'something')
,('def', '321', 'abc.xyz#something.com')
,('ghi', '123', 'def.321#something.com');
with contactCTE(rowNo, firstName, lastName, emailID)
as
(
select
ROW_NUMBER() OVER (ORDER BY firstName, lastName DESC)
,firstName
,lastName
,emailID
from
#contact
)
update c1
set
emailID = c2.emailID
from
contactCTE c1
inner join contactCTE c2 on c1.rowNo +1 = c2.rowNo;
select * from #contact
If your data is ordered differently just modify the ORDER BY part in contactCTE to reflect this
Person
| p_id | n_name | l_name | address | city | state | zip |
Customer
| p_id | reward_points| balance |
Person_PhoneNum
| ppn_id | p_id | number |
Main issue is that I want to attempt making a Retrieve Stored Procedure that can search by any of Person's fields as well as phone number or p_id BUT I want it to be able to handle NULL values from the parameters. Here is the Stored Procedure below:
CREATE PROCEDURE RetrieveCust(
#p_id AS varchar(50),
#f_name AS varchar(50),
#l_name AS varchar(50),
#address AS varchar(50),
#city AS varchar(50),
#state AS varchar(50),
#zip AS varchar(50),
#number AS varchar(50))
AS
BEGIN
END
I understand that I need to join the tables in order to match results but I don't know what I could do to handle NULL values. Any help would be amazing!
Any NULL in a parameter should match any value in the tables. Whenever you compare a parameter to a table field OR that comparison with a test for a null parameter:
( #f_name = f_name ) or ( #f_name is null )
then AND all those comparisons together to make up your retrieval.
The comparison against the phone number when phone number is null will result in more that one row if they have more than one phone number so Select DISTINCT on p_id.
What does Customer have to do with the query? You're not selecting on any field in that table and you don't appear to be returning any values from the procedure.
your where statement could be something like this
where (f_name = #f_name or #f_name is null)