I have a table of people (CarOwners
) and the types of cars they own
+-------+-------+
| Name | Model |
+-------+-------+
| Bob | Camry |
| Bo
This counts the number of rows for each name
using a common table expression(cte) with count()
over().
Then the matches
cte uses a self-join where the names do not match, the models match, the count of models for each name match, and one of those names is 'Lisa'
. The having
clause ensures that count of matched rows (count(*)
) matches the number of models that name
has.
matches
itself would only return the name
of each person, so we join back to the source table t
to get the full list of models for each match.
;with cte as (
select *
, cnt = count(*) over (partition by name)
from t
)
, matches as (
select x2.name
from cte as x
inner join cte as x2
on x.name <> x2.name
and x.model = x2.model
and x.cnt = x2.cnt
and x.name = 'Lisa'
group by x2.name, x.cnt
having count(*) = x.cnt
)
select t.*
from t
inner join matches m
on t.name = m.name
rextester demo: http://rextester.com/SUKP78304
returns:
+-------+-------+
| name | model |
+-------+-------+
| Kevin | Civic |
| Kevin | Focus |
+-------+-------+
We could also write it without the ctes, but it makes it a little harder to follow:
select t.*
from t
inner join (
select x2.Name
from (
select *, cnt = count(*) over (partition by name)
from t
where name='Lisa'
) as x
inner join (
select *, cnt = count(*) over (partition by name)
from t
) as x2
on x.name <> x2.name
and x.model = x2.model
and x.cnt = x2.cnt
group by x2.name, x.cnt
having count(*) = x.cnt
) as m
on t.name = m.name