Reputation: 140
so the question is "Produce a list of those employees who have made bookings at the Sports Club more than 5 times in the last calendar year (this should be calculated and not hard coded). Order these by the number of bookings made."
what i am struggling with is being able to get todays year and then subtract 1 year aswell as showing ONLY one name of people appearing 5 times. this is what i have so far, but it doesnt work.
SELECT DISTINCT
FIRSTNAME,SURNAME,DATEBOOKED,MEMBERSHIPTYPEID,BOOKINGID,MEMBER.MEMBERID
FROM MEMBERSHIP,MEMBER,BOOKING
WHERE MEMBER.MEMBERID = BOOKING.MEMBERID
AND MEMBERSHIP.MEMBERSHIPTYPEID = 3 AND BOOKING.DATEBOOKED = (SYSDATE,
'DD/MON/YY -1') AND FIRSTNAME IN (
SELECT FIRSTNAME
FROM MEMBER
GROUP BY FIRSTNAME,SURNAME
HAVING COUNT(FIRSTNAME) >= 5
)
ORDER BY MEMBER.MEMBERID;
Upvotes: 0
Views: 73
Reputation: 146239
What you need is this day last year. There are various different ways of calculating that. For instance,
add_months(sysdate, -12)
or
sysdate - interval '1' year
The subquery looks a bit whacky too. What you're after is the number of BOOKING records in the last year. So the subquery should drive off the BOOKING table, and the date filter should be there.
Finally, there is a missing join condition between MEMBER and MEMBERSHIP. That's probably why you think you need that distinct
; fix the join and you'll get the result set you want and not a product. One advantage of the ANSI 92 explicit join syntax is that it stops us from missing joins.
Your query needs to be sorted by the number of bookings, so you need to count those and sort by the total. This means you don't actually need a subquery at all.
So your query should look something like:
SELECT MEMBER.MEMBERID
, MEMBER.FIRSTNAME
, MEMBER.SURNAME
, count(BOOKING.BOOKID) as no_of_bookings
FROM MEMBER
inner join MEMBERSHIP
on MEMBER.MEMBERID = MEMBERSHIP.MEMBERID
inner join BOOKING
on MEMBER.MEMBERID = BOOKING.MEMBERID
WHERE MEMBERSHIP.MEMBERSHIPTYPEID = 3
and BOOKING.DATEBOOKED >= add_months(trunc(sysdate), -12)
GROUP BY MEMBER.MEMBERID
, MEMBER.FIRSTNAME
, MEMBER.SURNAME
HAVING COUNT(*) >= 5
ORDER BY no_of_bookings desc;
Here is a SQL Fiddle demo for my query.
Upvotes: 3
Reputation: 1269923
I think this answers the question:
SELECT m.FIRSTNAME, m.SURNAME, m.MEMBERID
FROM MEMBER m JOIN
BOOKING b
ON m.MEMBERID = b.MEMBERID JOIN
MEMBERSHIP ms
ON ms.MEMBERID = m.MEMBERID
WHERE ms.MEMBERSHIPTYPEID = 3 AND
B.DATEBOOKED >= SYSDATE - INTERVAL '1 YEAR'
GROUP BY m.FIRSTNAME, m.SURNAME, m.MEMBERID
HAVING COUNT(*) >= 5
ORDER BY COUNT(* DESC;
Table aliases make the query much easier to write and to read.
Upvotes: 0
Reputation: 1041
SELECT
FIRSTNAME,SURNAME,DATEBOOKED,MEMBERSHIPTYPEID,BOOKINGID,MEMBER.MEMBERID
FROM MEMBERSHIP,MEMBER,BOOKING
WHERE MEMBER.MEMBERID = BOOKING.MEMBERID
AND MEMBERSHIP.MEMBERSHIPTYPEID = 3 AND BOOKING.DATEBOOKED between (SYSDATE) and
(sysdate - interval '1' year)
AND FIRSTNAME IN (
SELECT distinct FIRSTNAME
FROM MEMBER
GROUP BY FIRSTNAME,SURNAME
HAVING COUNT(FIRSTNAME) >= 5
)
ORDER BY MEMBER.MEMBERID;
Upvotes: 0