0

I would like to generate a list of all days where every sailor booked a boat in that particular day.

The table scheme is as follows:

CREATE TABLE SAILOR(
SID INTEGER NOT NULL,
NAME VARCHAR(50) NOT NULL,
RATING INTEGER NOT NULL,
AGE FLOAT NOT NULL,
PRIMARY KEY(SID)
);

CREATE TABLE BOAT(
BID INTEGER NOT NULL,
NAME VARCHAR(50) NOT NULL,
COLOR VARCHAR(50) NOT NULL,
PRIMARY KEY(BID)
);

CREATE TABLE RESERVE (
SID INTEGER NOT NULL REFERENCES SAILOR(SID),
BID INTEGER NOT NULL REFERENCES BOAT(BID),
DAY DATE NOT NULL,
PRIMARY KEY(SID, BID, DAY));

The data is as follows:

INSERT INTO SAILOR(SID, NAME, RATING, AGE)
VALUES
  (64, 'Horatio', 7, 35.0),
  (74, 'Horatio', 9, 35.0);

INSERT INTO BOAT(BID, NAME, COLOR)
VALUES
  (101, 'Interlake', 'blue'),
  (102, 'Interlake', 'red'),
  (103, 'Clipper', 'green'),
  (104, 'Marine', 'red');

INSERT INTO RESERVE(SID, BID, DAY)
VALUES+
  (64, 101, '09/05/98'),
  (64, 102, '09/08/98'),
  (74, 103, '09/08/98');

I have tried using this code:

SELECT DAY
FROM RESERVE R
WHERE NOT EXISTS (
SELECT SID
FROM SAILOR S
EXCEPT
SELECT S.SID
FROM SAILOR S, RESERVE R
WHERE S.SID = R.SID)
GROUP BY DAY;

but it returns a list of all days, no exception. The only day that it should return is "09/08/98". How do I solve this?

1
  • Note: PRIMARY KEY(SID, BID, DAY)); is wrong. it allows a boat to be lended multiple times on a single date(or: a person to lease multiple ships on a single day) Commented Jun 29, 2019 at 19:48

2 Answers 2

2

I would phrase your query as:

SELECT r.DAY
FROM RESERVE r
GROUP BY r.DAY
HAVING COUNT(DISTINCT r.SID) = (SELECT COUNT(*) FROM SAILOR);

Demo

The above query says to return any day in the RESERVE table whose distinct SID sailor count matches the count of every sailor.

This assumes that SID sailor entries in the RESERVE table would only be made with sailors that actually appear in the SAILOR table. This seems reasonable, and can be enforced using primary/foreign key relationships between the two tables.

Sign up to request clarification or add additional context in comments.

2 Comments

@RafaelPintodeFreitas . . . This was the first answer by over 15 minutes. It includes an explanation and a demo. I think this is the better answer and deserves to be accepted.
Sorry to revive the dead post, but you're right, @GordonLinoff! Thank you for the answer, Tim!
1

Taking a slightly different approach of just counting unique sailors per day:

SELECT day FROM (
  SELECT COUNT(DISTINCT sid), day FROM reserve GROUP BY day
) AS sailors_per_day
WHERE count = (SELECT COUNT(*) FROM sailor);
+------------+
| day        |
|------------|
| 1998-09-08 |
+------------+

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.