Identifying the next unwatched episode in a series - sql

I need to write a query in SQL that will identify the next unwatched episode in a series by a user. I have tables containing user history (userID, episodeID and show titleID) and Episode (episodeID(PK), episodeName and playCount), where the history table stores the episodeIDs of all watched episodes and the episode table contains all possible episodes.
I had hoped to do some sort of join between the two selecting by 'userID, titleID but i'm going in circles.
I've been learning SQL for about 5 hours in total so have no idea where to begin on this, any help gratefully received. I'm aware the code below is horrible and very clunky (please don't assume any prior knowledge!)
I've tried a left join, but this will return all data irrespective of user.
Create table Actor(
actorID integer primary key,
first_name text not null,
last_name text not null
);
create table AppearsIn(
actorID integer,
seriesID integer primary key
);
create table Series(
seriesID text,
titleID text,
episodeID text,
releaseDate date
);
create table Episode(
episodeID text primary key,
episodeName text,
playCount integer,
actorID integer
);
create table title(
titleID text primary key,
actorID integer,
titleName text,
genre text,
ageRating integer,
releaseDate date
);
create table history(
userID integer,
titleID text,
episodeID text
);
create table user (
userID integer not null,
fullName text not null,
Email text not null,
dateOfBirth date not null,
subscriptionEndDate date not null
);
insert into Actor (actorID, first_name, last_name)
values (76547, 'tom', 'cruise');
insert into Actor (actorID, first_name, last_name)
values (345, 'val', 'kilner');
insert into AppearsIn (actorID, seriesID)
values (345, 1);
insert into Series (seriesID, titleID, episodeID, releaseDate)
values ('WDS2', 'WalkingDead', 'WDS2E1', '1991-02-02');
insert into Series (seriesID, titleID, episodeID, releaseDate)
values ('WDS2', 'WalkingDead', 'WDS2E2', '1991-02-02');
insert into Series (seriesID, titleID, episodeID, releaseDate)
values ('WDS2', 'WalkingDead', 'WDS2E3', '1991-02-02');
insert into Series (seriesID, titleID, episodeID, releaseDate)
values ('WDS2', 'WalkingDead', 'WDS2E4', '1991-02-02');
insert into Series (seriesID, titleID, episodeID, releaseDate)
values ('WDS2', 'WalkingDead', 'WDS2E5', '1991-02-02');
insert into Series (seriesID, titleID, episodeID, releaseDate)
values ('WDS2', 'WalkingDead', 'WDS2E6', '1991-02-02');
insert into Series (seriesID, titleID, episodeID, releaseDate)
values ('WDS2', 'WalkingDead', 'WDS2E7', '1991-02-02');
insert into Series (seriesID, titleID, episodeID, releaseDate)
values ('WDS2', 'WalkingDead', 'WDS2E8', '1991-02-02');
insert into Episode (episodeID, episodeName, actorID, playCount)
values ('WDS2E1', 'A', 76547, 1);
insert into Episode (episodeID, episodeName, actorID, playCount)
values ('WDS2E2', 'B', 76547, 1);
insert into Episode (episodeID, episodeName, actorID, playCount)
values ('WDS2E3', 'C', 76547, 1);
insert into Episode (episodeID, episodeName, actorID, playCount)
values ('WDS2E4', 'D', 76547, 0);
insert into Episode (episodeID, episodeName, actorID, playCount)
values ('WDS2E5', 'E', 76547, 0);
insert into history (userID, titleID, episodeID)
values (8924, 'Walking Dead','WDS2E1');
insert into history (userID, titleID, episodeID)
values (8924, 'Walking Dead', 'WDS2E2');
insert into history (userID, titleID, episodeID)
values (8924, 'Walking Dead', 'WDS2E3');
insert into user (userID, fullName, Email, dateOfBirth, subscriptionEndDate)
values (8924, 'bill123', 'bill123#warmpost.com', '1970-02-12', '2019-06-05');
insert into title (titleID, actorID, titleName, genre, ageRating, releaseDate)
values ('WalkingDead', 123455, 'The Walking Dead', 'Drama', 15, '2015-01-01');
This is the query I tried:
SELECT * FROM Episode
LEFT JOIN history ON history.episodeID = Episode.EpisodeID
Where playcount <1
limit 1;

It sounds like you're just having issues with the join. Here's a page on how joins work. From that page:
(INNER) JOIN: Returns records that have matching values in both tables
LEFT (OUTER) JOIN: Return all records from the left table, and the matched records from the right table
RIGHT (OUTER) JOIN: Return all records from the right table, and the matched records from the left table
FULL (OUTER) JOIN: Return all records when there is a match in either left or right table
So, if you want only movies that user has seen, you could try replacing LEFT JOIN with RIGHT JOIN, or change the order in which you specify the tables.
I'm currently not able to test this myself, but hopefully this is what you're looking for.
SELECT * FROM Episode
RIGHT JOIN history ON history.episodeID = Episode.EpisodeID
WHERE playcount < 1
LIMIT 1;

Related

Get first and last record for each group

I have 2 tables like
My output should look like this. Basically, latest and the first status for each user_unique_access_id along with the timestamp
I tried the below query but my output has duplicated records.
select
distinct u.user_unique_access_id,
first_value(ul.status) over (partition by u.user_unique_access_id
order by
ul.created_timestamp asc) as first_status,
min(ul.created_timestamp) as first_created_at,
first_value(ul.status) over (partition by u.user_unique_access_id
order by
ul.created_timestamp desc) as current_status,
max(ul.created_timestamp) as last_created_at
from
public.users u
join public.user_location ul on
u.user_key = ul.user_key
group by
u.user_unique_access_id,
u.user_name,
ul.status,
ul.created_timestamp ;
DDL and DML statement
create table public.users ( user_key serial primary key, user_name varchar(20), user_unique_access_id varchar(20) );
create table public.user_location( user_key bigint not null, STATUS VARCHAR (512) not null, CREATED_TIMESTAMP timestamp not null, foreign key (user_key) references public.users (user_key) );
insert
into
public.users ( user_unique_access_id, user_name)
values('ABC_1', 'ABC');
insert
into
public.users ( user_unique_access_id, user_name)
values('ABC_2', 'ABC');
insert
into
public.user_location (user_key, status, created_timestamp)
values(1, 'Entrance', current_timestamp);
insert
into
public.user_location (user_key, status, created_timestamp)
values(1, 'Building A', current_timestamp);
insert
into
public.user_location (user_key, status, created_timestamp)
values(1, 'Building B', current_timestamp);
insert
into
public.user_location (user_key, status, created_timestamp)
values(1, 'Exit', current_timestamp);
insert
into
public.user_location (user_key, status, created_timestamp)
values(2, 'Entrance', current_timestamp);
insert
into
public.user_location (user_key, status, created_timestamp)
values(2, 'Building A', current_timestamp);
You can get the "first" and the "last" record using DISTINCT ON. Use that in two derived tables (one for the "first", one for the "last" record) and left join these to users.
SELECT u.user_unique_access_id,
f.status,
f.created_timestamp,
l.status,
l.created_timestamp
FROM users u
LEFT JOIN (SELECT DISTINCT ON (ul.user_key)
ul.user_key,
ul.status,
ul.created_timestamp
FROM user_location ul
ORDER BY ul.user_key ASC,
ul.created_timestamp DESC) f
ON f.user_key = u.user_key
LEFT JOIN (SELECT DISTINCT ON (ul.user_key)
ul.user_key,
ul.status,
ul.created_timestamp
FROM user_location ul
ORDER BY ul.user_key ASC,
ul.created_timestamp ASC) l
ON l.user_key = u.user_key;
(I would have linked a db<>fiddle but your DML is pretty useless as the timestamps are all the same.)

Analytical Query in SQL for MIN, MAX, and AVG

I am trying to figure out a query for this question: for each major, list the number of students, minimum GPA, maximum GPA, average GPA, minimum age, maximum age, and average age. (Show GPA with 2 decimal points, age with no decimal points. You may find it useful to create a view with one of the previous queries for this one.)
This is the script to create the table for SQL!
REM drop all the tables. Note that you need to drop the
REM dependent table first before dropping the base tables.
drop table Reg;
drop table Student;
drop table Course;
REM Now create all the tables.
create table Student
(
sid char(10) primary key,
sname varchar(20) not null,
gpa float,
major char(10),
dob DATE
);
create table Course
(
cno char(10) primary key,
cname varchar(20) not null,
credits int,
dept char(10)
);
create table Reg
(
sid references Student(sid) on delete cascade,
cno references Course(cno) on delete cascade,
grade char(2),
primary key (sid, cno)
);
REM Now insert all the rows.
insert into Student values ('111', 'Joe', 3.5 , 'MIS', '01-AUG-2000');
insert into Student values ('222', 'Jack', 3.4 , 'MIS', '12-JAN-1999');
insert into Student values ('333', 'Jill', 3.2 , 'CS', '15-MAY-1998');
insert into Student values ('444', 'Mary', 3.7 , 'CS', '17-DEC-2001');
insert into Student values ('555', 'Peter', 3.8 , 'CS', '19-MAR-1999');
insert into Student values ('666', 'Pat', 3.9, 'Math', '31-MAY-2000');
insert into Student values ('777', 'Tracy', 4.0, 'Math', '18-JUL-1997');
insert into Course values ('c101', 'intro', 3 , 'CS');
insert into Course values ('m415', 'database', 4 , 'Bus');
insert into Course values ('m215', 'programming', 4 , 'Bus');
insert into Course values ('a444', 'calculus', 3 , 'Math');
insert into Reg values ('111', 'c101', 'A');
insert into Reg values ('111', 'm215', 'B');
insert into Reg values ('111', 'm415', 'A');
insert into Reg values ('222', 'm215', 'A');
insert into Reg values ('222', 'm415', 'B');
insert into Reg values ('333', 'c101', 'A');
insert into Reg values ('444', 'm215', 'C');
insert into Reg values ('444', 'm415', 'B');
insert into Reg values ('555', 'c101', 'B');
insert into Reg values ('555', 'm215', 'A');
insert into Reg values ('555', 'm415', 'A');
insert into Reg values ('666', 'c101', 'A');
This is what I have so far:
SELECT major,
count(distinct SID) as students,
round(min(gpa), 2),
round(max(gpa), 2),
round(avg(gpa), 2),
trunc(min(sysdate - dob)/365) as min_age,
trunc(max(sysdate - dob)/365) as max_age,
trunc(avg(sysdate - dob)/365) as avg_age,
FROM Student
GROUP BY MAJOR;
According to your input I've made a query that I belive will show you the results. (It was kind hard to read the tables the way you posted it). The syntax may differ according to your DBMS (SQL Server, MySQL, REdshift, Postgres, etc)
Here is the query:
SELECT major,
COUNT(*) as students,
ROUND(MIN(gpa), 2) as min_gpa,
ROUND(MAX(gpa), 2) as max_gpa,
ROUND(AVG(gpa), 2) as avg_gpa,
MIN(DATEDIFF(year, current_date, dob)) as min_age,
MAX(DATEDIFF(year, current_date, dob)) as max_age,
AVG(DATEDIFF(year, current_date, dob)) as avg_date
FROM students st left join Course co on co.dept = st.major
GROUP BY major
Your query is completely fine (just remove comma(,) after avg_age.
SELECT major,
count(distinct SID) as students,
round(min(gpa), 2) as MinGPA,
round(max(gpa), 2) as MaxGPA,
round(avg(gpa), 2) as AvgGPA,
round(min(sysdate - dob)/365,0) as min_age,
round(max(sysdate - dob)/365,0) as max_age,
round(avg(sysdate - dob)/365,0) as avg_age
FROM Student
GROUP BY MAJOR;
You can also use months_between() with floor() to get the same result:
select * from student;
SELECT major,
count(distinct SID) as students,
round(min(gpa), 2) as MinGPA,
round(max(gpa), 2) as MaxGPA,
round(avg(gpa), 2) as AvgGPA,
floor(min(months_between(trunc((sysdate)), dob)) /12) as min_age,
floor(max(months_between(trunc((sysdate)), dob)) /12) as max_age,
floor(avg(months_between(trunc((sysdate)), dob)) /12) as avg_age
FROM Student
GROUP BY MAJOR;

SQL Finding multiple combinations in 2 tables (with all records)

I have two tables, one with some user configurations (#USERCONFIG) and the other (#COMBINATIONS), multiples combinations of configurations I need to find in the first table.
CREATE TABLE #COMBINATIONS (INDEX1 INT, MENU CHAR(10))
CREATE TABLE #USERCONFIG (USERID VARCHAR(10), MENU VARCHAR(10))
INSERT INTO #COMBINATIONS VALUES (1, 'ABC300')
INSERT INTO #COMBINATIONS VALUES (1, 'ABC400')
INSERT INTO #COMBINATIONS VALUES (2, 'ABC100')
INSERT INTO #COMBINATIONS VALUES (2, 'ABC500')
INSERT INTO #COMBINATIONS VALUES (2, 'ABC600')
INSERT INTO #USERCONFIG VALUES ('SMITHJ', 'ABC100')
INSERT INTO #USERCONFIG VALUES ('SMITHJ', 'ABC500')
INSERT INTO #USERCONFIG VALUES ('SMITHJ', 'ABC600')
INSERT INTO #USERCONFIG VALUES ('SMITHC', 'ABC100')
INSERT INTO #USERCONFIG VALUES ('SMITHC', 'ABC500')
INSERT INTO #USERCONFIG VALUES ('SMITHA', 'ABC100')
INSERT INTO #USERCONFIG VALUES ('SMITHA', 'ABC200')
INSERT INTO #USERCONFIG VALUES ('SMITHA', 'ABC300')
INSERT INTO #USERCONFIG VALUES ('SMITHA', 'ABC400')
INSERT INTO #USERCONFIG VALUES ('SMITHA', 'ABC600')
With this example data, I want the resultset to look like this:
'SMITHJ', '2'
'SMITHA', '1'
'SMITHC', '2'
Where it will return all users that have a match of configurations from the combinations table.
Any help would be appreciated.
The following will list users and the complete combinations they have. If it helps, you can think of it as the recipe-ingredient and user-ingredient textbook problem:
SELECT alluser.USERID, index_menu.INDEX1
FROM (SELECT DISTINCT USERID FROM #USERCONFIG) AS alluser
CROSS JOIN #COMBINATIONS AS index_menu
LEFT JOIN #USERCONFIG AS user_menu ON alluser.USERID = user_menu.USERID AND index_menu.MENU = user_menu.MENU
GROUP BY alluser.USERID, index_menu.INDEX1
HAVING COUNT(index_menu.MENU) = COUNT(user_menu.MENU)
This snippet will get that result:
IF OBJECT_ID('tempdb..#COMBINATIONS') IS NOT NULL DROP TABLE #COMBINATIONS;
IF OBJECT_ID('tempdb..#USERCONFIG') IS NOT NULL DROP TABLE #USERCONFIG;
CREATE TABLE #COMBINATIONS (INDEX1 INT, MENU VARCHAR(10));
CREATE TABLE #USERCONFIG (USERID VARCHAR(10), MENU VARCHAR(10));
INSERT INTO #COMBINATIONS (INDEX1, MENU) VALUES
(1, 'ABC301'),
(1, 'ABC401'),
(2, 'ABC102'),
(2, 'ABC502'),
(2, 'ABC602');
INSERT INTO #USERCONFIG (USERID, MENU) VALUES
('SMITHJ', 'ABC102'),
('SMITHJ', 'ABC502'),
('SMITHJ', 'ABC602'),
('SMITHC', 'ABC102'),
('SMITHC', 'ABC502'),
('SMITHA', 'ABC102'),
('SMITHA', 'ABC200'),
('SMITHA', 'ABC301'),
('SMITHA', 'ABC401'),
('SMITHA', 'ABC602');
SELECT USERID, INDEX1
FROM
(
SELECT uconf.USERID, comb.INDEX1,
COUNT(*) AS Total,
DENSE_RANK() OVER (PARTITION BY uconf.USERID ORDER BY COUNT(*) DESC, comb.INDEX1 ASC) AS Rnk
FROM #USERCONFIG uconf
INNER JOIN #COMBINATIONS comb
ON comb.MENU = uconf.MENU
GROUP BY uconf.USERID, INDEX1
) q
WHERE Rnk = 1
ORDER BY Total DESC, USERID;
Returns:
USERID INDEX1
SMITHJ 2
SMITHA 1
SMITHC 2

What is wrong with this JOIN statement in SQL?

I am working on this tutorial about SQL. In Step 2 of 2, it is asked to use the JOIN command to link 2 people from the persons list using information from the friends list. I edited the provided code and obtained the code included below: the relevant part starts with select persons.fullname, persons2.fullname. However, the last paragraph of the code ('relevant code') does not yield any result nor error message. Am I doing something wrong?
Code
CREATE TABLE persons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
fullname TEXT,
age INTEGER);
INSERT INTO persons (fullname, age) VALUES ("Bobby McBobbyFace", "12");
INSERT INTO persons (fullname, age) VALUES ("Lucy BoBucie", "25");
INSERT INTO persons (fullname, age) VALUES ("Banana FoFanna", "14");
INSERT INTO persons (fullname, age) VALUES ("Shish Kabob", "20");
INSERT INTO persons (fullname, age) VALUES ("Fluffy Sparkles", "8");
CREATE table hobbies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
person_id INTEGER,
name TEXT);
INSERT INTO hobbies (person_id, name) VALUES (1, "drawing");
INSERT INTO hobbies (person_id, name) VALUES (1, "coding");
INSERT INTO hobbies (person_id, name) VALUES (2, "dancing");
INSERT INTO hobbies (person_id, name) VALUES (2, "coding");
INSERT INTO hobbies (person_id, name) VALUES (3, "skating");
INSERT INTO hobbies (person_id, name) VALUES (3, "rowing");
INSERT INTO hobbies (person_id, name) VALUES (3, "drawing");
INSERT INTO hobbies (person_id, name) VALUES (4, "coding");
INSERT INTO hobbies (person_id, name) VALUES (4, "dilly-dallying");
INSERT INTO hobbies (person_id, name) VALUES (4, "meowing");
CREATE table friends (
id INTEGER PRIMARY KEY AUTOINCREMENT,
person1_id INTEGER,
person2_id INTEGER);
INSERT INTO friends (person1_id, person2_id)
VALUES (1, 4);
INSERT INTO friends (person1_id, person2_id)
VALUES (2, 3);
/* personal contribution starts here
select persons.fullname,hobbies.name
from persons
join hobbies
on hobbies.person_id=persons.id;
/* select persons.fullname, persons2.fullname
from persons
join persons persons2
join friends
on persons.fullname=friends.person1_id and persons2.fullname=friends.person2_id; */
/* relevant code: */
select persons.fullname, persons2.fullname
from persons
join friends
on persons.fullname=friends.person1_id
join persons persons2
on persons2.fullname=friends.person2_id;
[tutorial (c) khanacademy.org]
join friends
on persons.fullname=friends.person1_id
You're only including friends whose person1_id equals a person's fullname. Since person1_id is an integer and fullname is text, those will never be equal. You probably want:
select persons.fullname, persons2.fullname
from persons
join friends
on persons.id=friends.person1_id
join persons persons2
on persons2.id=friends.person2_id;

Relational algebra one to many, division

I have seen many examples of division but none helped me understand how to solve the following problem:
Relations are:
Patient (Pid, Did, Pname, Disease, Severity)
Doctor (Did, Cname, Dname, Specialty)
Clinic (Cname, Mname, Type, City)
Question is: Find all pairs of patient ID and city such that the patient doesn't suffer from flu, and was treated in all the clinics in that city.
From what I've seen I need to divide the patients without flu by....? I think that it should be a table with all the clinics in a certain city, but how do I get that, and for each possible city?
Thanks
so... this is kind of complicated... pay special attention to the sample data I included in the tables.
http://sqlfiddle.com/#!2/04eac4/15/0
http://sqlfiddle.com/#!2/04eac4/17/0
I have no idea where division was supposed to take place...?
First we need to know how many clinics are in each city:
select city, count(cid) as c_count from clinic group by city
Then we need to know where each patient has been treated for anything besides the flu...
select patient.pid, patient.pname, clinic.city,
count(distinct clinic.cid) as p_c_count
from patient
join patient_doctor
on patient.pid = patient_doctor.pid
join doctor
on patient_doctor.did = doctor.did
join clinic
on doctor.cid = clinic.cid
where patient_doctor.disease not in ('Flu')
group by patient.pid, patient.pname, clinic.city
This joins all the tables together so that we can link PID and CID. Then we want only information that on patients that does not include a diagnosis of the flu. After, we group by the patient information and the clinic city so that we can count the number of clinics that patient went to for each city. Keep in mind, Patient A can go to Clinic 1 in the first city and be treated for the flu and even if he gets treated for the flu at a different clinic in a different city, the way you phrased the question allows that person to show up in results for the first city/clinic.... Does that makes any sense?
Then we need to join those two results. If the number of clinics in each city is equal to the number of clinics a patient visited per city, without being diagnosed with the flu, we get this:
select p_info.pid, c_ct_info.city
from (select city, count(cid) as c_count from clinic group by city) as c_ct_info
join (
select patient.pid, patient.pname, clinic.city,
count(distinct clinic.cid) as p_c_count
from patient
join patient_doctor
on patient.pid = patient_doctor.pid
join doctor
on patient_doctor.did = doctor.did
join clinic
on doctor.cid = clinic.cid
where patient_doctor.disease not in ('Flu')
group by patient.pid, patient.pname, clinic.city ) as p_info
on c_ct_info.city = p_info.city
where c_count = p_c_count;
Now. This excludes anyone who just visited one clinic and wasn't diagnosed with the flu but didn't go any of the other clinics in that city.
Just in case that sqlfiddle dies one day... here is the tables and data I used:
Create table Clinic (
CID int not null primary key,
Cname varchar(100),
Mname varchar(100),
Type tinyint,
City varchar(100)
);
insert into Clinic values (1,'Clinic 1','Mname 1', 1, 'City 1');
insert into Clinic values (2,'Clinic 2','Mname 2', 1, 'City 1');
insert into Clinic values (3,'Clinic 3','Mname 3', 1, 'City 2');
Create table Doctor (
DID int not null primary key,
Dname varchar(100),
Specialty varchar(100),
CID int,
foreign key (CID) references Clinic (CID)
);
insert into Doctor values (1, 'House', 'Internal Medicine', 1);
insert into Doctor values (2, 'Dr Who', 'General Practice', 1);
insert into Doctor values (3, 'Dr Dave', 'General Practice', 1);
insert into Doctor values (4, 'Dr Four', 'General Practice', 2);
insert into Doctor values (5, 'Dr Five', 'General Practice', 3);
insert into Doctor values (6, 'Dr Six', 'General Practice', 3);
create Table Patient (
PID int not null primary key,
PName varchar(100)
);
insert into Patient values (1, 'P. One');
insert into Patient values (2, 'P. Two');
insert into Patient values (3, 'P. Three');
insert into Patient values (4, 'P. Four');
insert into Patient values (5, 'P. Five');
Create table Patient_Doctor (
PDID int not null auto_increment primary key,
PID int not null,
DID int,
Disease varchar(100),
Severity tinyint,
foreign key (PID) references Patient (PID),
foreign key (DID) references Doctor (DID)
);
insert into Patient_Doctor values (null, 1, 1, 'Flu', 1);
insert into Patient_Doctor values (null, 1, 4, 'Flu', 1);
insert into Patient_Doctor values (null, 1, 5, 'Flu', 1);
-- shouldn't be in our results because they were diagnosed with the flu in each city
insert into Patient_Doctor values (null, 2, 2, 'Other', 1);
insert into Patient_Doctor values (null, 2, 4, 'Other', 1);
insert into Patient_Doctor values (null, 2, 5, 'Other', 1);
-- should be in our results because they attended every clinic in every city and
-- did not get diagnosed with the flu at any location
insert into Patient_Doctor values (null, 3, 1, 'Other', 1);
insert into Patient_Doctor values (null, 3, 4, 'Other', 1);
insert into Patient_Doctor values (null, 3, 6, 'Flu', 1);
-- should show up in our results for City 1 because they attended all the clinics in that
-- city and were not diagnosed with the flu. this person should NOT show up in our results
-- for city 2 because they were diagnosed with the flu at a clinic there.
insert into Patient_Doctor values (null, 4, 3, 'Other', 1);
-- should NOT show up in any results. although they weren't diagnosed with the flu, they
-- did not attend each clinic in that city.
insert into Patient_Doctor values (null, 5, 2, 'Flu', 1);
-- should NOT show up in results... meets none of the criteria
if we would add this data:
insert into Patient values (6, 'P. Six');
insert into Patient_Doctor values (null, 6, 5, 'Other', 1);
we should expect to see that person in our results because there's only one clinic in city 2 and they were not diagnosed with the flu there...
Things I changed:
Patient_Doctor: PID, DID, Disease, Severity
Patient: PID, PName
Clinic and Doctor are now joined by CID instead of CName
I highly suggest you create another table for Disease so that you are not repeating the same information over and over again. This table would include the fields Disease_ID and Disease_Description. The disease would then be linked to the patient by the Disease_ID.