sql not a group by expression, not able to join 3 tables - sql

im trying to connect 3 tables together, it works just fine however when i try to group them by a certain column it shows me not a group by expression:
my tables:
create table userss (
username varchar2(25)not null ,
password varchar2(25) ,
userTypeID number(8) not null,
gender char(1),
dateCreated date,
lname varchar2(10),
fname varchar2(10),
constraint username1_pk primary key (username),
CONSTRAINT gender1_ck CHECK (gender='M' or gender='F'),
constraint userTypeID_fk foreign key(userTypeID) references userType (userTypeId)
);
create table doctor (
docID number(8) not null ,
docBioData varchar2(50),
username varchar2(25)not null ,
SpecID number(3),
post_id number(5) not null ,
constraint docID_pk primary key(docID),
constraint username4_fk foreign key (username) references userss(username),
constraint specID2_fk foreign key (specID) references speciality(specID),
constraint post_id_fk foreign key (post_id) references positions(post_id)
);
create table rating (
ratID number(10) not null ,
rat_date date,
rat_comment varchar2(100),
rat_rating number(1) not null,
docID number(8) not null ,
patID number(8) not null,
constraint ratID_pk primary key(ratID),
constraint docID_fk foreign key (docID) references doctor(docID),
constraint patID2_fk foreign key (patID) references patient(patID),
constraint rating_ck check (rat_rating between 1 and 5)
);
and my code is:
select d.docid, (fname|| ' '|| lname) "Doctor Name", count(r.rat_rating), avg(r.rat_rating)
from userss u, doctor d, rating r
where u.username = d.username and d.docid = r.docid and rat_date > TO_DATE('01-JAN-2020', 'DD-MON-YYYY')
group by d.docid
order by d.docid desc;

In your SELECT there is 2 columns before the COUNT and the AVG, therefore you have to GROUP BY those 2 columns.
Depending on your version, you cannot group by on an alias, you would need to encapsulate your first query.
select id, Doctor_Name, COUNT(rat_rating), AVG(rat_rating) from (
select d.docid AS id, (fname|| ' '|| lname) AS Doctor_Name, r.rat_rating, r.rat_rating
from userss u, doctor d, rating r
where u.username = d.username and d.docid = r.docid and rat_date > TO_DATE('01-JAN-2020', 'DD-MON-YYYY')
) A
group by id, Doctor_Name
order by id desc
You could on the other hand delete the "Doctor Name" column from your query, and it should work

Related

Many to many relationships in SQL. Can t get more than one result

I'm designing a simple movie database. Point of it is to have 2 M:N relationships.
So far I have design it like "central-base" database and it look like this.
GENRES(ID,GENRE_TYPE)- Many to many
ACTORS (ID, FULL_NAME, DOB) - many to many
DESCRIPTIONS(ID,DESCRIPTION)
DIRECTORS(ID, FULL_NAME, DOB)
PROFITS(ID, AMOUNT)
BUDGETS(ID, AMOUNT)
MOVIES(ID, TITLE, LENGTH, YEAR, GENRE, CAST, BUDGET, PROFIT, DIRECTED_BY)**
*those two are created to redefine M:N*
**MOVIE_GENRES(ID, MOVIE_ID, GENRE_ID)
MOVIE_CAST(ID, MOVIE_ID, ACTOR_ID)**
my question is when i do it like this, i'm only getting 1 actor per movie, or one genre per movie.
The point is to have 2 actors for each movie, and 2 or 1 genre for each movie.
Since i m new one in field of sql please help me. I m using Oracle Live SQL.
qlq
Create a table for the genres:
CREATE TABLE Genres (
ID NUMBER(8,0)
GENERATED ALWAYS AS IDENTITY
CONSTRAINT Genres__ID__PK PRIMARY KEY,
NAME VARCHAR2(30)
CONSTRAINT Genres__Name__NN NOT NULL
CONSTRAINT Genres__Name__U UNIQUE
);
and you can insert sample data into it:
INSERT INTO Genres ( Name )
SELECT 'Comedy' FROM DUAL UNION ALL
SELECT 'Horror' FROM DUAL UNION ALL
SELECT 'Period Drama' FROM DUAL UNION ALL
SELECT 'Documentary' FROM DUAL
and a table for the people that contains the data specific to that person:
CREATE TABLE People (
ID NUMBER(8,0)
GENERATED ALWAYS AS IDENTITY
CONSTRAINT People__ID__PK PRIMARY KEY,
FIRST_NAME VARCHAR2(200)
CONSTRAINT People__fn__nn NOT NULL,
LAST_NAME VARCHAR2(200)
CONSTRAINT People__ln__nn NOT NULL,
DATE_OF_BIRTH DATE
CONSTRAINT People__dob__nn NOT NULL
);
Those people can take various roles in a film so create a table to describe the roles a person can take:
CREATE TABLE Roles (
ID NUMBER(8,0)
GENERATED ALWAYS AS IDENTITY
CONSTRAINT Roles__ID__PK PRIMARY KEY,
ROLE VARCHAR2(30)
CONSTRAINT Roels__Role__NN NOT NULL
CONSTRAINT Roles__Role__U UNIQUE
);
for example:
INSERT INTO Roles ( Role )
SELECT 'Actor' FROM DUAL UNION ALL
SELECT 'Director' FROM DUAL UNION ALL
SELECT 'Producer' FROM DUAL;
This way you don't need to create a new table for each role a person takes on in the movie.
Then you can create a table with only the data that is specific to the movie (and not related to any of the other tables):
CREATE TABLE Movies (
ID NUMBER(8,0)
GENERATED ALWAYS AS IDENTITY
CONSTRAINT Movies__ID__PK PRIMARY KEY,
TITLE VARCHAR2(300)
CONSTRAINT Movies__title__nn NOT NULL,
LENGTH INTERVAL DAY TO SECOND,
RELEASE_DATE DATE,
BUDGET NUMBER(12,2),
PROFIT NUMBER(12,2)
);
Then you can create tables that describe the relationships between the tables:
CREATE TABLE Movie_People (
ID NUMBER(8,0)
GENERATED ALWAYS AS IDENTITY
CONSTRAINT Movie_People__ID__PK PRIMARY KEY,
Movie_ID NUMBER(8,0)
CONSTRAINT Movie_People__Movie_ID__NN NOT NULL
CONSTRAINT Movie_People__Movie_ID__FK REFERENCES Movies( ID ),
Role_ID NUMBER(8,0)
CONSTRAINT Movie_People__Role_ID__NN NOT NULL
CONSTRAINT Movie_People__Role_ID__FK REFERENCES Roles( ID ),
Person_ID NUMBER(8,0)
CONSTRAINT Movie_People__Person_ID__NN NOT NULL
CONSTRAINT Movie_People__Person_ID__FK REFERENCES People( ID ),
CONSTRAINT Movie_People__M_R_P__U UNIQUE( Movie_ID, Role_ID, Person_ID )
);
and
CREATE TABLE Movie_Genres (
ID NUMBER(8,0)
GENERATED ALWAYS AS IDENTITY
CONSTRAINT Movie_Genres__ID__PK PRIMARY KEY,
Movie_ID NUMBER(8,0)
CONSTRAINT Movie_Genres__Movie_ID__NN NOT NULL
CONSTRAINT Movie_Genres__Movie_ID__FK REFERENCES Movies( ID ),
Genre_ID NUMBER(8,0)
CONSTRAINT Movie_Genres__Genre_ID__NN NOT NULL
CONSTRAINT Movie_Genres__Genre_ID__FK REFERENCES Genres( ID ),
CONSTRAINT Movie_Genres__M_G__U UNIQUE( Movie_ID, Genre_ID )
);
Then if you want to add an actor for a movie to the database:
INSERT INTO Movie_People (
Movie_ID,
Role_ID,
Person_ID
) VALUES (
( SELECT ID FROM Movies WHERE title = 'The Muppet Christmas Carol' ),
( SELECT ID FROM Roles WHERE role = 'Actor' ),
( SELECT ID FROM People WHERE first_name = 'Michael' AND last_name = 'Caine' )
)
and if you want to find the movies with multiple genres then, for example:
SELECT Movie_ID
FROM Movie_Genres
WHERE Genre_ID IN (
SELECT ID
FROM Genres
WHERE Name IN ( 'Comedy', 'Horror' )
)
GROUP BY Movie_ID
HAVING COUNT( Genre_ID ) = 2;

Select from 3 tables with foreign key

Need to display next: all fNAME and lNAME from table username that have position of "Admin" from location "3RD Floor", with IN clause
create table company
(
CODE_COMPANY char(30),
NAME_COMPANY varchar2(30) not null,
MAIL_COMPANY varchar2(30) null,
constraint PK_CODE_COMPANY primary key (CODE_COMPANY),
);
create table USERNAME
(
NAME_USERNAME varchar2(30),
USER_LOCATION number,
fNAME varchar2 (30) not null,
lNAME varchar2 (30) not null,
PHONE_USER char(13) null,
USER_POSITION varchar2 (30),
check (USER_POSITION in('Admin', 'Superadmin', 'Technician', 'Student')),
constraint PK_NAME_USERNAME primary key (NAME_USERNAME),
constraint FK_USER_LOCATION foreign key (USER_LOCATION) references uLOCATION (LOCATION)
);
create table uLOCATION
(
LOCATION number,
CODE_COMPANY char(30),
NAME_LOCATION varchar2(30) not null,
FLOOR_LOCATION varchar2(10),
check (FLOOR_LOCATION in ('MAIN_FLOOR', '1ST FLOOR', '2ND FLOOR', '3RD FLOOR')),
constraint PK_LOCATION primary key (LOCATION),
constraint FK_CODE_COMPANY_L foreign key (CODE_COMPANY) references company (CODE_COMPANY),
);
SELECT U.fName, U.lName
FROM USERNAME AS U
WHERE U.USER_POSITION = 'Admin'
AND
U.USER_LOCATION IN (
SELECT L.LOCATION
FROM uLOCATION AS L
WHERE L.FLOOR_LOCATION = '3RD FLOOR'
);
select fName, lName
from USERNAME, uLOCATION, COMPANY
where uLOCATION.LOCATION = USERNAME.USER_LOCATION and COMPANY.CODE_COMPANY = uLOCATION.CODE_COMPANY;
But how to specify, that I need user Admin from NAME_COMPANY ABC?
how to add 2 more WHERE clause?
Slight modifying SQLRaptor's answer for NAME_COMPANY:
SELECT U.fName, U.lName
FROM USERNAME AS U
WHERE U.USER_POSITION = 'Admin'
AND
U.USER_LOCATION IN (
SELECT L.LOCATION
FROM uLOCATION AS L JOIN COMPANY AS C
ON L.CODE_COMPANY=C.CODE_COMPANY
WHERE L.FLOOR_LOCATION = '3RD FLOOR' AND C.NAME_COMPANY = 'ABC'
);

Select from 3 tables with IN clause

Need to display next: all fNAME and lNAME from table username that have position of "Admin" and work in 'ABC' company (NAME_COMPANY), with IN clause.
create table company
(
CODE_COMPANY char(30),
NAME_COMPANY varchar2(30) not null,
MAIL_COMPANY varchar2(30) null,
constraint PK_CODE_COMPANY primary key (CODE_COMPANY),
);
create table USERNAME
(
NAME_USERNAME varchar2(30),
USER_LOCATION number,
fNAME varchar2 (30) not null,
lNAME varchar2 (30) not null,
PHONE_USER char(13) null,
USER_POSITION varchar2 (30),
check (USER_POSITION in('Admin', 'Superadmin', 'Technician', 'Student')),
constraint PK_NAME_USERNAME primary key (NAME_USERNAME),
constraint FK_USER_LOCATION foreign key (USER_LOCATION) references uLOCATION (LOCATION)
);
create table uLOCATION
(
LOCATION number,
CODE_COMPANY char(30),
NAME_LOCATION varchar2(30) not null,
FLOOR_LOCATION varchar2(10),
check (FLOOR_LOCATION in ('MAIN_FLOOR', '1ST FLOOR', '2ND FLOOR', '3RD FLOOR')),
constraint PK_LOCATION primary key (LOCATION),
constraint FK_CODE_COMPANY_L foreign key (CODE_COMPANY) references company (CODE_COMPANY),
);
If I understand your question correctly, you want the following query. Not sure why you would use an IN instead of a standard = however I've included both with one commented.
select
user.fName,
user.lName
from
username as user
inner join ulocation as location
on location.location = user.user_location
inner join company as company
on company.code_company = location.code_company
where
user.user_position = 'Admin'
and name_company in ('A','B','C') -- not needed if only checking for one company
-- if only one company, change to: name_company = 'ABC'
I think you are looking for:
select u.*
from username u
where u.user_position = 'admin' and
u.ulocation in (select l.location
from ulocation l join
ucompany c
on l.code_company = c.code_company
where c.name_company = 'ABC'
);

Get Max record from query SQL Server

I have the following tables
CREATE TABLE Staff
(
staffID int,
fullName varchar(100) NOT NULL,
s_category varchar(25),
s_email varchar(50),
s_contactNo int,
speciality varchar(100),
qualifications varchar(250),
pre_employment varchar(200),
salary numeric(8,2),
staff_gender char(1),
staff_joined_date datetime,
branch_allocated int,
CONSTRAINT PK_Staff
PRIMARY KEY (staffID),
CONSTRAINT FK_Staff_Branch
FOREIGN KEY (branch_allocated) REFERENCES Branch(branchID)
ON DELETE CASCADE,
CONSTRAINT CHK_StaffGender CHECK (staff_gender='M' OR staff_gender='F'),
CONSTRAINT CHK_FullName CHECK (fullName NOT LIKE '%[^A-Za-z ]%'),
CONSTRAINT CHK_SALARY CHECK (salary>0 AND salary<=150000)
);
CREATE TABLE Appointment
(
appID int,
patientId int,
staffId int,
appDateTime DateTime,
CONSTRAINT PK_Appointment PRIMARY KEY (appID),
CONSTRAINT FK_Appointment_Patient
FOREIGN KEY (patientId) REFERENCES Patient(patientID)
ON DELETE CASCADE,
CONSTRAINT FK_Appointment_Staff
FOREIGN KEY (staffId) REFERENCES Staff(staffID)
ON DELETE CASCADE,
CONSTRAINT CHK_AppointmentDate CHECK (appDateTime>=GETDATE())
);
I want to get the doctor(s) with maximum number of patients.
I have created the query as follows.
SELECT
s.staffID AS 'ID',s.fullName AS 'Name', COUNT(a.appID) AS 'Number of Patients'
FROM
Staff s
INNER JOIN
Appointment a ON s.staffID = a.staffId
GROUP BY
s.staffID, s.fullName
ORDER BY
'Number of Patients' DESC
But this returns all doctors. Can you help me to find the doctor with the largest number of patients?
WITH cte AS (
SELECT
s.staffID AS ID,
s.fullName AS Name,
COUNT(a.appID) AS [Number of Patients],
DENSE_RANK() OVER (ORDER BY COUNT(a.appID) DESC) AS rank
FROM Staff s
LEFT JOIN Appointment a
ON s.staffID = a.staffId
GROUP BY s.staffID, s.fullName
)
SELECT
ID, Name, [Number of Patients]
FROM cte
WHERE rank = 1;
Can you try this
SELECT TOP number|percent column_name(s)
FROM table_name
WHERE condition;
on your situation SELECT TOP 1

sqlplus using of sub query

I have 3 tables, and have to find out the applicant number, name and total number of position each applicant applied for.
CREATE TABLE APP (
appNum varchar2(10) not null,
appName varchar2(70),
constraint applicant_Pkey primary key (appNum)
);
CREATE TABLE POS (
posNum varchar2(10) not null,
posStartOfferDt date not null,
constraint pos_Pkey primary key (posNum, posStartOfferDt)
);
CREATE TABLE APPLICATION (
appcnPosNum varchar2(10) not null,
appcnPosStOffrDt date not null,
appcnAppNum varchar2(10) not null,
appcnDt date,
constraint application_Pkey primary key (appcnPosNum, appcnPosStOffrDt, appcnAppNum),
constraint application_Fkey1 foreign key (appcnPosNum, appcnPosStOffrDt) references POSITION(posNum, posStartOfferDt),
constraint application_Fkey2 foreign key (appcnAppNum) references APPLICANT(appNum)
);
I have tried using sub query, natural join but all not working out for me.
SELECT appNum, appName, COUNT(*)
FROM applicant
JOIN application ON applicant.appNum = application.appcnAppNum
GROUP BY appNum, appName