简体   繁体   中英

SQL Server Function to return a value or a NULL if no results

I am trying to create a scalar function that will return an employee number if a position ( jobcode here) is filled, or a NULL value if it's vacant ( A ctive or T erminated status).

数据预览

I happen to know that the position called manager (10061) is vacant at store 517. The same position is filled at 536. I'm accomplishing this with a CTE, which is preventing me from using WHERE EXISTS , my first attempt at solving this.

The closest I'm getting is this:

with cte as (
select store, empno, name, jobcode, jobtitle, status, lasthiredate, terminationdate, row_number() over (partition by jobcode, store order by terminationdate desc) as rn
from #temp
)
Select distinct a.store, b.empno, a.name, a.jobcode, a.jobtitle, a.status, a.rn
from cte a
left outer join cte b on a.jobcode = b.jobcode and a.store = b.store and a.status <> b.status
where a.jobcode = 10061
order by a.store, a.rn

And here is some sample data if you want to play along at home:

create table #temp (    [Store] int,    [EmpNo] int,    [Name] varchar(11),     [Jobcode] int,  [Dept] int,     [JobTitle] varchar(8),  [LastHireDate] date,    [Status] varchar(1),    [TerminationDate] date); 
Insert into #temp values (  119,    5042105,    'Gary D.',  10721,  10,     'Director',     '7/7/2003',     'T',    '1/18/2015'); 
Insert into #temp values (  119,    5391105,    'Sonia H.',     10721,  10,     'Director',     '12/19/2008',   'A',    NULL); 
Insert into #temp values (  119,    8155608,    'Paul W.',  10721,  10,     'Director',     '3/20/2017',    'T',    '11/30/2017'); 
Insert into #temp values (  119,    11952311,   'LARRY B.',     10721,  11,     'Director',     '4/15/2010',    'T',    '3/14/2012'); 
Insert into #temp values (  119,    19065019,   'Gary D.',  10721,  10,     'Director',     '7/7/2003',     'T',    '3/24/2017'); 
Insert into #temp values (  119,    19073019,   'Timothy P.',   10721,  10,     'Director',     '4/30/2013',    'T',    '12/5/2017'); 
Insert into #temp values (  119,    27230127,   'Jeffery F.',   10721,  10,     'Director',     '1/17/2010',    'T',    '12/21/2015'); 
Insert into #temp values (  119,    89113289,   'Timothy S.',   10721,  10,     'Director',     '8/3/2015',     'T',    '5/14/2019'); 
Insert into #temp values (  119,    89209289,   'Michael B.',   10721,  10,     'Director',     '12/17/2015',   'A',    NULL); 
Insert into #temp values (  119,    89453589,   'Harold H.',    10721,  10,     'Director',     '2/21/2018',    'T',    '5/7/2019'); 
Insert into #temp values (  119,    89604489,   'Jason B.',     10721,  10,     'Director',     '5/17/2017',    'A',    NULL); 
Insert into #temp values (  119,    89931089,   'Jeffery F.',   10721,  10,     'Director',     '1/17/2010',    'A',    NULL); 
Insert into #temp values (  119,    99371499,   'William A.',   10721,  10,     'Director',     '11/2/1998',    'A',    NULL); 
Insert into #temp values (  119,    99728099,   'K. Renee H.',  10721,  10,     'Director',     '9/11/1989',    'T',    '3/24/2017'); 
Insert into #temp values (  517,    11263511,   'Michael D.',   10061,  3,  'Manager',  '1/19/2015',    'T',    '7/27/2015'); 
Insert into #temp values (  517,    11544211,   'Richard L.',   10061,  3,  'Manager',  '10/10/2005',   'T',    '12/14/2014'); 
Insert into #temp values (  536,    3507003,    'Jeffrey S.',   10061,  3,  'Manager',  '2/18/2002',    'T',    '6/8/2012'); 
Insert into #temp values (  536,    12558412,   'John S.',  10061,  3,  'Manager',  '9/27/2010',    'A',    NULL); 

Ideally the function's output would be

Store   |   Jobcode |   EmpNo
 536        10061       12558412
 517        10061       NULL

Any help is so greatly appreciated.

To get the information that you look for, you just need to look at the record with the most recent LastHireDate for each store and jobcode . If this record has status 'A' , the position is staffed, else it is vacant.

I would suggest to use a correlated subquery for filtering instead of row_number() . In this situation this can be an efficicent solution, especially with an index on (store, jobcode, LastHireDate) .

select store, jobcode, case when status = 'A' then name end employeeName
from #temp t
where t.LastHireDate = (
    select max(t1.LastHireDate) 
    from #temp t1 
    where t1.store = t.store and t1.jobcode = t.jobcode
)
order by store, jobcode

Demo on DB Fiddle :

store | jobcode | employeeName
----: | ------: | :-----------
  119 |   10721 | null        
  517 |   10061 | null        
  536 |   10061 | John S.     

Here is a scalar function to do that:

CREATE FUNCTION dbo.CheckAvailability (@jobcode INT, @store INT)
RETURNS INT
AS
BEGIN
DECLARE @return int
SELECT @return = t.jobcode
FROM temp1 AS t
WHERE t.Jobcode = @jobcode
  AND t.Store = @store
  AND t.Status NOT IN ('A','T')

RETURN (@return)
END

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM