tsql - Getting those records that have a match of all records in another table -


within realm of problem have 3 entities:

  1. user
  2. position
  3. license

then have 2 relational (many-to-many) tables:

  1. positionlicense - 1 connects position license ie. licenses required particular position
  2. userlicense - 1 connects user license ie. licenses particular user has. additional complexity: user licenses have validity date range (validfrom , validto)

the problem

these input variables:

  • userid identifiers particular user
  • rangefrom defines lower date range limit
  • rangeto defines upper date range limit

what need get? particular user (and date range) need list of positions particular user can work at. problem user must have @ least licenses required every matching position.

i'm having huge problems writing sql query list.

if @ possible using single sql query (can have additional ctes of course). if can convince me doing in several queries more efficient i'm willing listen in.

some workable data

copy , runs script. 3 users, 3 positions, 6 licenses. mark , john should have match not jane.

create table [user] (     userid int identity not null         primary key,     name nvarchar(100) not null ) go  create table position (     positionid int identity not null         primary key,     name nvarchar(100) not null ) go  create table license (     licenseid int identity not null         primary key,     name nvarchar(100) not null ) go  create table userlicense (     userid int not null         references [user](userid),     licenseid int not null         references license(licenseid),     validfrom date not null,     validto date not null,     check (validfrom < validto),     primary key (userid, licenseid) ) go  create table positionlicense (     positionid int not null         references position(positionid),     licenseid int not null         references license(licenseid),     primary key (positionid, licenseid) ) go  insert [user] (name) values ('mark mechanic'); insert [user] (name) values ('john pilot'); insert [user] (name) values ('jane has arts phd not medical.');  insert position (name) values ('mechanic'); insert position (name) values ('pilot'); insert position (name) values ('doctor');  insert license (name) values ('mecha'); insert license (name) values ('flying'); insert license (name) values ('medicine'); insert license (name) values ('phd'); insert license (name) values ('phycho'); insert license (name) values ('arts');  insert positionlicense (positionid, licenseid) values (1, 1); insert positionlicense (positionid, licenseid) values (2, 2); insert positionlicense (positionid, licenseid) values (2, 5); insert positionlicense (positionid, licenseid) values (3, 3); insert positionlicense (positionid, licenseid) values (3, 4);  insert userlicense (userid, licenseid, validfrom, validto) values (1, 1, '20110101', '20120101'); insert userlicense (userid, licenseid, validfrom, validto) values (2, 2, '20110101', '20120101'); insert userlicense (userid, licenseid, validfrom, validto) values (2, 5, '20110101', '20120101'); insert userlicense (userid, licenseid, validfrom, validto) values (3, 4, '20110101', '20120101'); insert userlicense (userid, licenseid, validfrom, validto) values (3, 6, '20110101', '20120101'); 

resulting solution

i've setup resulting solution based on accepted answer provides simplified solution problem. if you'd play query hit edit/clone (whether you're logged in or not). can changed:

  • three variables:
    1. two variable set date range (@from , @to)
    2. user id (@user)
  • you can toggle commented code in first cte switch code between overlapping user licenses or partially overlapping ones.

this makes number of assumptions (ignores presence of time in datetime columns, assumes obvious primary keys) , skips joins pull in user name, position details, , like. (and implied user had hold licenses full period specified, right?)

select pl.positionid  positionlicense pl   left outer join (--  licenses user has entirety (sp?) of specified date range                    select licenseid                     userlicense                     userid = @userid                      , @rangefrom <= validfrom                      , @rangeto >= validto) li    on li.licenseid = pl.licenseid  group pl.positionid   --  licenses required position held user  having count(pl.licenseid) = count(li.licenseid) 

no data can't debug or test it, or close should trick.


Comments

Popular posts from this blog

php - What is the difference between $_SERVER['PATH_INFO'] and $_SERVER['ORIG_PATH_INFO']? -

fortran - Function return type mismatch -

queue - mq_receive: message too long -