My Databases look like so:
PEAK (NAME, ELEV, DIFF, MAP, REGION)
CLIMBER (NAME, SEX)
PARTICIPATED (TRIP_ID, NAME)
CLIMBED (TRIP_ID, PEAK, WHEN)
I need help w/ writing an SQL query for these 2 example scenarios:
This is what I have for the first query:
SELECT PEAK
FROM CLIMBED
WHERE TRIP_ID IN
(SELECT TRIP_ID
FROM PARTICIPATED
WHERE NAME IN ('MARK','MARY')
GROUP BY TRIP_ID
HAVING COUNT(*) = 2
);
The problem w/ this query is it only gives me all of the peaks that Mark and Mary have climbed during the same trip they took together. I need to somehow get the peaks that they both have climbed, but that they weren't together for.
For the second query I have no clue how to get the COUNT() of each peak that all the participants climbed during the specific TRIP_ID.
For your first question, you should just be able to remove the Having clause to get climbs where either Mark or Mary participated.
SELECT PEAK
FROM CLIMBED
WHERE TRIP_ID IN
(SELECT TRIP_ID
FROM PARTICIPATED
WHERE NAME IN ('MARK','MARY')
GROUP BY TRIP_ID
);
Leaving the Having clause there means that you need both Mark and Mary to be in the Participated table for a particular trip for the trip_id to give you the 2 rows mandated by the having clause.
To get the peaks where one has climbed, but not the other, use your original query, but change the having clause to be 1:
SELECT PEAK
FROM CLIMBED
WHERE TRIP_ID IN
(SELECT TRIP_ID
FROM PARTICIPATED
WHERE NAME IN ('MARK','MARY')
GROUP BY TRIP_ID
HAVING COUNT(*) = 1
);
This works because given the where condition, Count(*) will be:
Having clauses limit queries based on conditions after grouping, so usually are based on aggregates like Count(*), which will give you the number of records that are "contained" within each grouping.
The second question is a little tougher, but if I understand it correctly you should be able to use something like this:
SELECT climbed.trip_id, sum(peak.elev)
FROM climbed LEFT JOIN participated ON climbed.trip_id = participated.trip_id
LEFT JOIN peak ON climbed.peak = peak.name
GROUP BY climbed.trip_id
HAVING sum(peak.elev) > 500000;
This works because using the left join, the elevation for each climber is duplicated; then when you sum for each trip, it adds the elevation for each climber.