I am trying to separate first and last name . I have a column called 'Fullname' and it has first and last name and a comma all in one column. I've tried the below but I get an error " its not a valid number". When I remove the comma it works, so I am not sure how to incorporate a comma in the formula so it can work.
,substr(Fullname,1,',') as Lastname
,substr(Fullname,',',' ') as Firstname
Column
Fullname
Brown,John N
Green,Julie T
Desired results
Lastname FirstName
Brown John
Green Julie
You can use regexp_substr():
select regexp_substr(name, '[^,]+', 1, 1) as lastname,
regexp_substr(name, '[^, ]+', 1, 2) as firstname
The second argument to SUBSTR() is the position of the substring, the third argument is the length of the substring. It will not automatically search for a delimiter if you use strings there instead of numbers. You can use LOCATE() to find the positions that you want.
SUBSTR(Fullname, 1, LOCATE(Fullname, ',')-1) AS Lastname,
SUBSTR(Fullname, LOCATE(Fullname, ',')+1) AS Firstname
Can be performed in Classical way by using instr inside substr function as the following case :
select substr(fullname,1,instr(fullname,',')-1) Firstname,
substr(fullname,instr(fullname,',')+1,length(fullname)) Lastname
from tab;
SQL Fiddle Demo
Related
So basically I need to get a part of the postcode string, all before an empty space
my current query is
select postcode, left(postcode, length(postcode) - strpos(' ', postcode))
from postcodetable
But it just doesn't return the post code correctly, example:
1st column is NW1 1AA, 2nd column should just be NW1 but instead it just repeats the first column
Your arguments to strpos() are in the wrong order. So you can do:
select postcode, left(postcode, length(postcode) - strpos(postcode, ' '))
from (values ('NW1 1AA')) v(postcode);
You can also do this using substring() with regular expressions:
select postcode, substring(postcode from '[^ ]+'::text)
I'm sure this is super easy, but how would I go about converting LastName,FirstName to LastName,FirstInitial?
For example changing Smith,John to Smith,J or Johnson,John to Johnson,J etc.
Thank You!
In case of LastName and FirstName columns:
select LastName,substr(FirstName,1,1)
from mytable
;
In case of a fullname saved in a single column:
select substr(fullname,1,instr(fullname || ',',',')-1) || substr(fullname,instr(fullname || ',',','),2)
from mytable
;
or
select regexp_replace (fullname,'([^,]*,?)(.).*','\1\2')
from mytable
;
Here is one way, using just "standard" instr and substr. Assuming your input is a single string in the format 'Smith,John':
select substr(fullname, 1, instr(fullname, ',')+1) from yourtable;
yourtable is the name of the table, and fullname is the name of the column.
instr(fullname, ',') finds the position of the comma within the input string (it would be 6 in 'Smith,John'); thensubstrtakes the substring that begins at the first position (the1in the function call) and ends at the position calculated byinstr`, PLUS 1 (to get the first initial as well).
In a table(football_team) the values in a column(names) looks like this Andrew Luck , QB . I want to split this column into 3 columns first_name,Last_name,position using PL/SQL functions.
i tried this
select regexp_substr(names,'[^ ,"]+',1,1) as first_name,
regexp_substr(names,'[^ ,"]+',1,2) as last_name,
regexp_substr(names,'[^ ,"]+',1,3) as position from football_team;
doesn't work
Can I make it by using only SUBSTR and INSTR functions.
Please help me. Thanks in advance.
Yes you could use string functions too but IMO regexp is much simpler here. Well as long as you can read regexps, YMMV.
The problem is in regular expressions. Try this instead:
with names(name) as (
select 'Andrew Luck , QB' from dual
union all
select 'John Doe , WB' from dual
)
select
regexp_substr(name, '^([[:alpha:]]+)', 1, 1, '', 1) as firstname
,regexp_substr(name, '^[[:alpha:]]+[[:space:]]+([[:alpha:]]+)', 1, 1, '', 1) as lasttname
,regexp_substr(name, '([[:alpha:]]+)$', 1, 1, '', 1) as position
from names
;
Returns:
FIRSTNAME LASTNAME POSITION
--------- -------- --------
Andrew Luck QB
John Doe WB
The firstname matching regular expressions explained:
^ -- start of the string
( -- start of subexpression group that is referenced by regexp_substr parameter #6 (subexpr)
[ -- start of matching character list
[:alpha:] -- character class expression: alphabet.
] -- end of matching character list
+ -- matches one or more occurrences of the preceding subexpression
) -- end of subexpression group
The explanantion of other two regexps are left as an excercise for the OP.
I have a column name that represents a person's name in the following format:
firstname [middlename] lastname [, Sr.|Jr.]
For, example:
John Smith
John J. Smith
John J. Smith, Sr.
How can I order items by lastname?
A correct and faster version could look like this:
SELECT *
FROM tbl
ORDER BY substring(name, '([^[:space:]]+)(?:,|$)')
Or:
ORDER BY substring(name, E'([^\\s]+)(?:,|$)')
Or even:
ORDER BY substring(name, E'([^\\s]+)(,|$)')
Explain
[^[:space:]]+ .. first (and longest) string consisting of one or more non-whitespace characters.
(,|$) .. terminated by a comma or the end of the string.
The last two examples use escape-string syntax and the class-shorthand \s instead of the long form [[:space:]] (which loses the outer level of brackets when inside a character class).
We don't actually have to use non-capturing parenthesis (?:) after the part we want to extract, because (quoting the manual):
.. if the pattern contains any parentheses, the portion of the text that
matched the first parenthesized subexpression (the one whose left
parenthesis comes first) is returned.
Test
SELECT substring(name, '([^[:space:]]+)(?:,|$)')
FROM (VALUES
('John Smith')
,('John J. Smith')
,('John J. Smith, Sr.')
,('foo bar Smith, Jr.')
) x(name)
SELECT *
FROM t
ORDER BY substring(name, E'^.*\\s([^\\s]+)(?=,|$)') ASC
While this should provide the sorting you are looking for, it would be a lot cheaper to store the name in multiple columns and index them based on which parts of the name you need to sort by.
You should use functional index for this purpose
http://www.postgresql.org/docs/7.3/static/indexes-functional.html
In your case somehow....
CREATE INDEX test1_lastname_col1_idx ON test1 (split_part(col1, ' ', 3));
SELECT * FROM test1 ORDER BY split_part(col1, ' ', 3);
I need to compare the value of a column (LASTNAME) with a system variable (:VARIABLE), but the variable is an email address, so I need to trim off the "#email.com" and "firstname." Some things I've tried:
select *
from TABLENAME
where LASTNAME LIKE :VARIABLE
select *
from TABLENAME
where LASTNAME IN :VARIABLE
I've been able to trim off the #email.com, can't figure out how to trim off FIRSTNAME. at the same time.
Regular expressions can help:
SQL> SELECT LTRIM(regexp_substr('firstname.lastname#abc.com','\.[^#]*'),'.') last_name from dual;
LAST_NAME
---------
lastname
Your query could then look like:
SELECT *
FROM tablename
WHERE UPPER(LTRIM(regexp_substr(:VARIABLE,'\.[^#]*'),'.')) = UPPER(lastname);
You can use a combination of SUBSTR and INSTR.
The instr function returns the location of a substring in a string. With this one you can locate the "."or the "#" char.
Then use the substr to get the substring from the begining to the previous located position
SELECT SUBSTR('Take the first four characters', 1, 4)
Use:
SELECT t.*
FROM TABLE t
WHERE t.lastname LIKE '%' || SUBSTR(:VARIABLE,
INSTR(:VARIABLE, '.') +1,
INSTR(:VARIABLE, '#')) || '%'
Add UPPER or LOWER to both sides if you need to be sure of case insensitive matching.
Reference:
SUBSTR
INSTR