Reputation: 1707
Hopefully an easy MS SQL Question! I have four tables:
Portfolio:
int portfolioId, string portfolioName
1,'PortFolio 1'
Trip:
int tripId, int portfolioId, int tripType, int maxPeople, string tripName
1, 1, 1, 20, 'Trip A'
2, 1, 1, 21, ’Trip B'
3, 1, 2, 22, ’Trip C'
Person:
int personId, int personStatus, string personName
1, 14, ‘Person 1'
2, 15, ‘Person 2'
3, 16, ‘Person 3'
TripPerson:
int personId, int tripId
1, 1
1, 3
2, 1
2, 2
For a given portfolioId, I’m trying to write a clean query that will give me the following columns:
tripId, countA, countB, tripType, tripName
Where: CountA: is the total number of Persons on the Trip. CountB: is the total number of people who are on that trip that have also been on at least one other trip with type of ‘2’. The number of rows returned must match the number of trips related to portfolio where portfolioId = 1, ordered by tripName.
Thoughts? I am using MS SQL, have a basic understanding of SQL, and this is driving me bananas.
Upvotes: 0
Views: 70
Reputation: 10284
You can write a query as:
With CTE1 as
(
-- Total number of persons on a trip:
select count(T.personId) as CountA , tripId
from TripPerson T
group by T.tripId
),
CTE2 as
(
-- Total number of people who are on a trip that have also been on
-- at least one other trip with type of '2'.
select Count (T2.personId)as CountB , CTE1.tripId ,CTE1.CountA
from TripPerson T2
inner join TripPerson T3 on T2.personId = T3.personId and T3.tripId =2
right join CTE1 on CTE1.tripId = T2.tripId
group by CTE1.tripId,CTE1.CountA
)
select CTE2.tripId, CTE2.CountA, CTE2.CountB, Trip.tripType, Trip.tripName
from CTE2
inner join Trip on Trip.tripId = CTE2.tripId
inner join Portfolio P on P.portfolioId = Trip.portfolioId
Upvotes: 1
Reputation: 466
This will get you result by joining to tripperson to find the count and using a left join to person again to find the same person who has been on multiple trips.
SELECT t.tripId, count(p.personid) countA, count(p2.personid) countB,
t.tripType, t.tripName, t.portfolioid
FROM TRIP t
JOIN TripPerson p ON p.tripid = t.tripid
LEFT JOIN (select tp.personid, count(*) cnt FROM TripPerson tp group by tp.personid) p2
ON p2.personid = p.personid and p2.cnt > 1
group by t.tripId, t.tripType, t.tripName, t.portfolioid
Upvotes: 0
Reputation: 6739
one option is you can use sub-queries to get the countA and countB, so the query looks like some thing below:
select trip.tripId, trip.tripType, trip.tripName,
(select count(personId) from TripPerson where tripId = trip.tripId) as countA,
(select count(personId) from TripPerson where tripId IN (trip.tripId, 2)) as countB
from Trip trip
where portfolioId = 1 order by trip.tripName
Upvotes: 0