To check if last name is part of first name - oracle-sqldeveloper

I am working on Data standardization rules, and one of the rules says, "If the last name is part of first name, then remove the last name from first name".
my Query- how do i check if first name column has the last name in it using oracle sql developer?
I tried using :
select fst_nm, lst_nm from emp where fst_nm = fst_nm || lst_nm ;
but this query returns '0' results.
Also, I tried another query:
select fst_nm, lst_nm, regexp_substr(fst_nm, '[^ ]+',1,1) from emp ;
I tried using the below query
select fst_nm, lst_nm from emp where fst_nm = fst_nm || lst_nm ;
but this query returns nothing, I mean '0' results.
Also, I tried another query:
select fst_nm, lst_nm, regexp_substr(fst_nm, '[^ ]+',1,1) from emp ;
expected result is:
fst_nm = john smith ;
lst_nm = smith
Actual result showing up is :
fst_nm = john ;
lst_nm = smith
Please help

You should be able to just do a blanket replace on the entire table:
UPDATE emp
SET fst_nm = REPLACE(fst_nm, lst_nm, '');
The reason this should work is that for those records where the last name does not appear as part of the first name, the replace would have no effect. Otherwise, the last name would be stripped from the first name.

You can use below logic
select length('saurabh rai'),instr('saurabh rai',' '),case when length('saurabh rai') > instr('saurabh rai',' ') then substr('saurabh',1,instr('saurabh rai',' ')-1) else 'saurabh rai' end as a from dual;
Update emp set fst_nm=(Case when length(fst_nm) > instr(fst_nm, ' ') then substr(fst_nm,1,instr(fst_nm,' ')-1) else fst_nm end);

Related

PostsgreSQL. How to return the number of records in the users table who have name Latifah, Elizabeth or Diana?

I have this :
SELECT count(*) FROM users
WHERE name = 'Latifah'
AND name = 'Elizabeth'
AND name = 'Diana';
It returns zero. What's wrong? Is there a way to make it shorter?
you can "aggregate" ORs to IN operator:
SELECT count(*)
FROM users
WHERE name IN ('Latifah','Elizabeth','Diana');
This is also worked:
SELECT count(*) FROM users
WHERE name = 'Latifah'
or name = 'Elizabeth'
or name= 'Diana';

PostgreSQL subquery split rows (error is more than one row returned by a subquery used as an expression)

this is my first post on stackoverflow so please be gentle. I have researched this problem and came up with many varied solutions...all of which seem to be just off from what I need. I have a postgresql subquery in a SELECT statement that returns multiple rows, which I know is obviously not ideal/allowed/sensible/etc.... However, this is the case for my current problem and I need to be able to take those multiple returned rows and apply them to every previous corresponding record row that they originally came out of.
Current Query:
SELECT cohead_number "Sales Order#",
cohead_custponumber "Purchase Order#",
item_number "Part Number",
item_descrip1 "Part Description",
CAST(shipitem_qty AS integer) "Item Quantity",
getPacklistItemLotSerial(shiphead_id, coitem_id) AS "LotNumbers" --this is the duplicating row subquery that I need listed in separate rows without changing other respective columns--
FROM cohead
LEFT JOIN coitem
ON coitem_cohead_id = cohead_id
LEFT JOIN shipitem
ON coitem_id = shipitem_orderitem_id
LEFT JOIN itemsite
ON coitem_itemsite_id = itemsite_id
LEFT JOIN item
ON itemsite_item_id = item_id
LEFT JOIN shiphead
ON shiphead_order_id = cohead_id
WHERE cohead_number = '79464' --this is just to test with one sales order instead of all (sales order being the input for the query)--
Results:
LINK: Results of above query here
What I Have Tried
Now, this line lets me split the column results via the delimiter ',' but I can't figure out how to get the results from this back into my original query's results:
(SELECT lot from regexp_split_to_table(getPacklistItemLotSerial(shiphead_id, coitem_id),', ') AS lot)
Results:
Here I input the shiphead_id and coitem_id for the example sales order so it can show you the resulting split column into rows.
SELECT lot from regexp_split_to_table(getPacklistItemLotSerial(22082, 50351),', ') AS lot
LINK: Results of Example
Please help walk me through what I need to do to achieve this. I imaging we need to declare some things and maybe join 2 tables in a more complex query...I don't really know. Thank you for any help you can offer.
EDIT
Added in the requested source code for the Function "getpacklistitemlotserial"
DECLARE
pShipheadId ALIAS FOR $1;
pOrderItemId ALIAS FOR $2;
_lotserial text;
_r RECORD;
_first BOOLEAN;
BEGIN
--Test to see if Lot/Serial Enabled
SELECT metric_value INTO _lotserial
FROM metric
WHERE ((metric_name='LotSerialControl')
AND (metric_value ='t'));
IF (FOUND) THEN
_lotserial := '';
_first := true;
FOR _r IN SELECT DISTINCT ls_number
FROM invdetail, invhist, shipitem, ls
WHERE ((shipitem_shiphead_id=pShipheadId)
AND (shipitem_orderitem_id=pOrderItemId)
AND (shipitem_invhist_id=invhist_id)
AND (invhist_id=invdetail_invhist_id)
AND (invdetail_ls_id=ls_id)) LOOP
IF (_first = false) THEN
_lotserial := _lotserial || ', ';
END IF;
_lotserial := _lotserial || _r.ls_number;
_first := false;
END LOOP;
RETURN _lotserial;
ELSE
RETURN '';
END IF;
END
Try:
SELECT DISTINCT cohead_number "Sales Order#",
cohead_custponumber "Purchase Order#",
item_number "Part Number",
item_descrip1 "Part Description",
CAST(shipitem_qty AS integer) "Item Quantity",
-- getPacklistItemLotSerial(shiphead.shiphead_id, coitem.coitem_id) AS "LotNumbers" --this is the duplicating row subquery that I need listed in separate rows without changing other respective columns--
CASE WHEN EXISTS(
SELECT metric_value FROM metric
WHERE metric_name='LotSerialControl' AND metric_value ='t'
)
THEN x.ls_number
ELSE ''
END AS "LotNumbers"
FROM cohead
LEFT JOIN coitem
ON coitem_cohead_id = cohead_id
LEFT JOIN shipitem
ON coitem_id = shipitem_orderitem_id
LEFT JOIN itemsite
ON coitem_itemsite_id = itemsite_id
LEFT JOIN item
ON itemsite_item_id = item_id
LEFT JOIN shiphead
ON shiphead_order_id = cohead_id
LEFT JOIN (
SELECT ls_number,
shipitem_shiphead_id, -- parameter: pShipheadId
shipitem_orderitem_id -- parameter pOrderItemId
FROM invdetail, invhist, shipitem, ls
WHERE
-- (shipitem_shiphead_id=pShipheadId)
-- AND (shipitem_orderitem_id=pOrderItemId)
(shipitem_invhist_id=invhist_id)
AND (invhist_id=invdetail_invhist_id)
AND (invdetail_ls_id=ls_id)
) x
ON ( x.shipitem_shiphead_id = shiphead.shiphead_id
AND
x.shipitem_orderitem_id = coitem.coitem_id
)
WHERE cohead_number = '79464'

How to fetch a part of string upto a chracter?

I want to fetch the names of employees from a table upto the character ':' but couldn't as substr and ltrim is not working as expected. Below given are given some examples:
ABINERI:REBECCA C
CARRINGTON:JAMES M
But I want them in the way given below:
REBECCA C ABINERI
JAMES M CARRINGTON
I just used the query below in Toad for Oracle:
<pre>
<b>select name from employees</b>
</pre>
Please try below query:
select SUBSTR(name,(INSTR(name,':')+1)) || ' ' || SUBSTR(name,1,(INSTR(name,':'))-1) from employees;
hope above query will resolve your issue.

Convert value to unique value (ex John to John_1)

The user writes his name and i want to store it into the database. If the name is already in the database i want to insert a postfix. ie Convert 'John' to the first one available between ('John_1', 'John_2' ... etc).
This is my way of doing this so far, but i'm sure there's a better way.
select n from
(
select 'John' n ,0 v
union
select 'John'||'_'||generate_series(1,100),generate_series(1,100)
) possible_names
where n not in
(select my_name from all_names u)
order by v
limit 1
Any suggestions?
If you need to worry about concurrency, the simplest way to guarantee uniqueness is by issuing insert statements until one succeeds. (This assumes you've a unique constraint, of course.)
Pseudocode:
while true
if db.execute(insert_sql, [..., name + postfix, ...])
break
end
counter += 1
postfix = '_' + counter
end
You can make the procedure run in a shorter amount of time by starting at the maximum existing postfix (see the other answers with approaches to do that).
An awkward alternative would be to find the maximum existing postfix using a select statement, and then to try to acquire an advisory lock on something unique to the applicable name and postfix, e.g. 'username:' + name + postfix. It's much less robust though, because it opens up the possibility of two transactions finding the same max_postfix, and then one transaction trying to acquire the lock immediately after other is done committing its insert and releasing that lock -- thus resulting in a duplicate.
SELECT CASE WHEN num IS NULL THEN 'John' ELSE 'John' || '_' || num END AS new_name
FROM (
SELECT max(substr(my_name, position('_' in my_name) + 1)::int) + 1 AS num
FROM all_names
WHERE my_name ilike 'John' || '_%'
) new_number
With all three instances of 'John' being where you pass in the name entered. (This is assuming that the user can't make an underscore part of their name and a number will always follow the underscore.)
Edit: This is also assuming that 'John' and 'john' should be treated the same. If they shouldn't, then replace the ilike with like instead.
CREATE FUNCTION get_username_proposal(text) RETURNS text AS $$
SELECT
CASE WHEN (SELECT COUNT(*) FROM all_names WHERE my_name = $1)=0 THEN
$1
ELSE
$1 || '_' || COALESCE(MAX(LTRIM(SUBSTRING(my_name FROM '_[0-9]+$'), '_')::int), 0)+1
END
FROM
all_names
WHERE
my_name ~ ($1 || '_[0-9]+$');
$$ LANGUAGE SQL STABLE;

Nested SELECT statement in a CASE expression

Greetings,
Here is my problem.
I need to get data from multiple rows and return them as a single result in a larger query.
I already posted a similar question here.
Return multiple values in one column within a main query but I suspect my lack of SQL knowledge made the question too vague because the answers did not work.
I am using Microsoft SQL 2005.
Here is what I have.
Multiple tables with CaseID as the PK, CaseID is unique.
One table (tblKIN) with CaseID and ItemNum(AutoInc) as the combined PK.
Because each person in the database will likely have more than one relative.
If I run the following, in a SQL query window, it works.
DECLARE #KINList varchar(1000)
SELECT #KINList = coalesce(#KINList + ', ','') + KINRel from tblKIN
WHERE CaseID = 'xxx' and Address = 'yyy'
ORDER BY KINRel
SELECT #KINList
This will return the relation of all people who live at the same address. the results look like this...
Father, Niece, Sister, Son
Now, the problem for me is how do I add that to my main query?
Shortened to relevant information, the main query looks like this.
SELECT DISTINCT
c.CaseID,
c.Name,
c.Address,
Relatives=CASE WHEN exists(select k.CaseID from tblKIN k where c.CaseID = k.CaseID)
THEN DECLARE #KINList varchar(1000)
SELECT #KINList = coalesce(#KINList + ', ','') + KINRel from tblKIN
WHERE CaseID = 'xxx' and Address = 'yyy'
ORDER BY KINRel
SELECT #KINList
ELSE ''
END
FROM tblCase c
ORDER BY c.CaseID
The errors I receive are.
Server: Msg 156, Level 15, State 1, Line 13
Incorrect syntax near the keyword 'DECLARE'.
Server: Msg 156, Level 15, State 1, Line 18
Incorrect syntax near the keyword 'ELSE'.
I tried nesting inside parenthesis from the DECLARE to the end of the SELECT #KINList.
I tried adding a BEGIN and END to the THEN section of the CASE statement.
Neither worked.
The source table data looks something like this. (periods added for readability)
tblCase
CaseID Name Address
10-001 Jim......100 Main St.
10-002 Tom....150 Elm St.
10-003 Abe.....200 1st St.
tblKIN
CaseID ItemNum Name Relation Address
10-001 00001 Steve...Son........100 Main St.
10-002 00002 James..Father....150 Elm St.
10-002 00003 Betty....Niece......150 Elm St.
10-002 00004 Greta...Sister.....150 Elm St.
10-002 00005 Davey..Son........150 Elm St.
10-003 00006 Edgar...Brother...200 1st St.
If I run the query for CaseID = 10-002, it needs to return the following.
CaseID Name Address.......Relatives
10-002 Tom...150 Elm St. ..Father, Niece, Sister, Son
I am sure this is probably a simple fix, but I just don't know how to do it.
Thank you for your time, and I apologize for the length of the question, but I wanted to be clear.
Thanks !!!
When I did something similar I had to create a scalar function to do the coalesce that returns the varchar result. Then just call it in the select.
CREATE FUNCTION GetRelatives
(
#CaseID varchar(10)
)
RETURNS varchar(1000)
AS
BEGIN
DECLARE #KINList varchar(1000)
SELECT #KINList = coalesce(#KINList + ', ','') + KINRel from tblKIN
WHERE CaseID = #CaseID
ORDER BY KINRel
RETURN #KINList
END
Then your select
SELECT DISTINCT
c.CaseID,
c.Name,
c.Address,
database.dbo.GetRelatives(c.CaseID) AS Relatives
FROM tblCase c
ORDER BY c.CaseID
You can create a FUNCTION which takes in the caseID as the arguement and returns true or false.
Since you are calling the nested query multiple times, its definitely a performance hit. A better solution is to execute the query and store the results in a temporary table.
Then pass this temporary table and the caseID to the FUNCTION and check for containment.