Reputation: 45
I have a table as follows:
create table table1(id integer,firstname text,lastname text);
Now I have another table create table table2(id integer,position integer);
I want to select rows with a lastname , where the lastname must be shared by ben and rob and firstnames must be ben and rob.
Now I also want the position of ben to be one lesser than that of rob, hence the result would be :
What should the sql query be ?
Upvotes: 0
Views: 3231
Reputation: 45
Gordon Linoff's solutions:
select nben.*, p.position
from names nben join
positions p
on nben.id = p.id and
nben.firstname = 'ben' join
names nrob
on nrob.firstname = 'rob' and
nrob.lastname = nben.lastname join
positions prob
on nrob.id = prob.id and
p.position = prob.position - 1
gives same result as:
select * from(select n.*, p.position
from names n join
position p
on n.id = p.id
where firstname in ('ben', 'rob') and
lastname in (select lastname
from names n join
position p
on n.id = p.id
where firstname in ('ben', 'rob')
group by lastname
having count(distinct firstname) = 2
)
)
as x,names,position
where (x.id!=names.id and names.id=position.id
and names.lastname=x.lastname
and (x.firstname='ben' and names.firstname='rob')
and x.position+1=position.position)
Upvotes: -1
Reputation: 45
This gives me the result i needed obtained from Gordon Linoff's solution:
select * from(select n.*, p.position
from names n join
position p
on n.id = p.id
where firstname in ('ben', 'rob') and
lastname in (select lastname
from names n join
position p
on n.id = p.id
where firstname in ('ben', 'rob')
group by lastname
having count(distinct firstname) = 2
)
)
as x,names,position
where
(x.id!=names.id and names.id=position.id and names.lastname=x.lastname
and (x.firstname='rob' and names.firstname='ben') and x.position=position.position+1)
or
(x.id!=names.id and names.id=position.id and names.lastname=x.lastname
and (x.firstname='ben' and names.firstname='rob') and x.position+1=position.position)
Upvotes: 0
Reputation: 1269873
To get the last name:
select lastname
from names n join
position p
on n.id = p.id
where firstname in ('ben', 'rob')
group by lastname
having count(distinct firstname) = 2 and
1+max(case when firstname = 'ben' then p.position end) = max(case when firstname = 'rob' then p.position end)
You can then get the original list with:
select n.*, p.position
from names n join
position p
on n.id = p.id
where firstname in ('ben', 'rob') and
lastname in (select lastname
from names n join
position p
on n.id = p.id
where firstname in ('ben', 'rob')
group by lastname
having count(distinct firstname) = 2 and
1+max(case when firstname = 'ben' then p.position end) = max(case when firstname = 'rob' then p.position end)
)
I think the following query answers your question, with the caveat that this combines the names into one row:
select nben.*, p.position, nrob.*, prob.position
from names nben join
positions p
on nben.id = p.id and
nben.firstname = 'ben' join
names nrob
on nrob.firstname = 'rob' and
nrob.lastname = nben.lastname join
positions prob
on nrob.id = prob.id and
p.position = prob.position - 1
Also, this is untested.
Upvotes: 2