Calculate a value with other values - sql

Let's make it simple:
USE Example1
CREATE TABLE Person
(PersonID int PRIMARY KEY IDENTITY(1,1),
FirstName nchar(20) NOT NULL,
LastName nchar(20) NOT NULL,
Salary money NOT NULL
)
CREATE TABLE Student
(StudentID int PRIMARY KEY IDENTITY(1,1),
FirstName nchar(20) NOT NULL,
LastName nchar(20) NOT NULL,
FatherID int NOT NULL,
MotherID int NOT NULL,
CONSTRAINT fk_Student_FatherID FOREIGN KEY (FatherID)
REFERENCES Person(PersonID),
CONSTRAINT fk_Student_MotherID FOREIGN KEY (MotherID)
REFERENCES Person(PersonID)
)
CREATE TABLE Registration
(RegistrationID int PRIMARY KEY IDENTITY(1,1),
StudentID int NOT NULL,
Date datetime NOT NULL,
MonthlyPayment ??????????
CONSTRAINT fk_Registration_StudentID FOREIGN KEY (StudentID)
REFERENCES Student(StudentID)
)
INSERT INTO Person VALUES ('John','Doe','1000')
INSERT INTO Person VALUES ('Mary','Poppins','800')
INSERT INTO Student VALUES ('Gary','Doe', 1, 2)
INSERT INTO Registration VALUES (1, getdate(),???)
I have a student that is going to make a registration in a school and have a monthly payment that is going do be FatherSalary*0.5 + MotherSalary*0.5 but I don't know how to make that happen. I'm new in SQL and maybe this is simple and I should know how to make it, but I don't and I need help.

Are you sure you need MonthlyPayment column in your table?
You can create table Registration without MonthlyPayment field and then create a view
create view vw_Registration
as
select
R.RegistrationID,
R.StudentID,
R.Date,
F.Salary * 0.5 + M.Salary * 0.5 as MonthlyPayment
from Registration as R
left outer join Student as S on S.StudentID = R.StudentID
left outer join Person as F on F.PersonID = S.FatherID
left outer join Person as M on M.PersonID = S.MotherId
SQL FIDDLE EXAMPLE

If the expression "FatherSalary*0.5 + MotherSalary*0.5" will not change, then you can use trigger i suppose.Your trigger will check the inserts to your Registration table. At the time of an insert, it will get the student id, then using this id it will get the necessary data from your student table and your Person table. At that moment, you will have access to the Money column for both father and mother. Calculate the result, and let the trigger to the insert for you.

A view sounds good at first hand, but I can imagine a scenario where you want to calculate a monthly payment based on the data available at a certain point in time so the monthly payment does not change everytime the father or mother has a change in salary...
In that case you can use this:
INSERT INTO Registration
(StudentID, Date, MonthlyPayment)
SELECT S.StudentID, getdate(), ISNULL(F.Salary, 0) * 0.5 + ISNULL(M.Salary, 0) * 0.5
FROM Student as S
left outer join Person as F on F.PersonID = S.FatherID
left outer join Person as M on M.PersonID = S.MotherId
WHERE S.StudentID = 1
SQL Fiddle

Related

how to join two/ three tables in postgresql

I am new to creating databases and want to know how to solve this problem or if I'm even doing it right.
I'm trying to join two/three tables, staff, role and staff_role together so that the staff can have more than one role and I'm not sure how to go about it any help is appreciated! , this is my code for these tables:
CREATE TABLE ROLE(
ROLE_ID SERIAL PRIMARY KEY,
ROLE_NAME VARCHAR(50) NULL);
Insert into role(role_name) values('Manager');
Insert into role(role_name) values('Glass_Fibre_Specialist');
Insert into role(role_name) values('Engine_Technician');
Insert into role(role_name) values('Electrician');
Insert into role(role_name) values('General_Technician');
CREATE TABLE STAFF(
STAFF_ID SERIAL PRIMARY KEY,
STAFF_FNAME VARCHAR(35) NOT NULL,
STAFF_LNAME VARCHAR(35) NOT NULL,
ADDR VARCHAR(100) NOT NULL,
POSTCODE VARCHAR(20) NOT NULL,
WORK_EMAIL VARCHAR(150) NOT NULL);
CREATE TABLE STAFF_ROLE(
STAFF_ID int NOT NULL REFERENCES STAFF(STAFF_ID),
ROLE_ID int NOT NULL REFERENCES ROLE(ROLE_ID));`
this is what I tried using to join my tables but I don't think it's right
SELECT
s.Staff,
r.role,
sr.Staff_role
FROM Staff s
INNER JOIN role AS r
ON r.StaffID = s.StaffID
INNER JOIN staff_role sr
ON sr.staff_roleId = r.roleId;
`
I have tried looking at how to join the tables but it has not worked/ I'm not too confident about how to do it, I have also tried adding two types of roles as well, but it kept coming up with errors and I'm kind of stuck

Get columns from one table to another

So I'll create a combination of all first names and all surnames from a table (Person).
insert into tabell_med_navn
select f.fornavn, e.etternavn
from person f cross join person e
These combinations should then be added to a table I have made earlier.
create table tabell_med_navn (
id int not null auto_increment,
fornavn varchar(40) null,
etternavn varchar(40) null,
primary key (id)
);
It is when I am trying to send the combination over it fails. Anybody know why it fails?
List the columns being inserted:
insert into tabell_med_navn (fornavn, etternavn)
select f.fornavn, e.etternavn
from person f cross join
person e;
This will assign a default value to the id column.

SQL - Subquery, SELECT from select

My database query :
CREATE DATABASE [College Assignment]
PRINT 'CREATE DATABASE College Assignment'
GO
USE [College Assignment]
CREATE TABLE Departments
(DEPART nvarchar(255) NOT NULL, D_NAME nvarchar(255), HEAD nvarchar(255),PRIMARY KEY (DEPART));
CREATE TABLE Courses
(COURSE_ID nvarchar(255) NOT NULL,
COURSE_NAME nvarchar(255),
"TYPE" nvarchar(255),
POINTS float,
DEPARTMENT_ID nvarchar(255),
PRIMARY KEY (COURSE_ID),
CONSTRAINT fk_dep
FOREIGN KEY (DEPARTMENT_ID) REFERENCES Departments(DEPART));
CREATE TABLE Students
(STUDENT_ID float NOT NULL,
S_NAME nvarchar(255),
CITY nvarchar(255),
PRIMARY KEY (STUDENT_ID));
CREATE TABLE Grades
(STUDENT_ID float NOT NULL,
COURSE_ID nvarchar(255) NOT NULL,
SEMESTER nvarchar(255),
TERM nvarchar(255),
GRADE smallint,
GRADE_SEM smallint,
PRIMARY KEY (STUDENT_ID, COURSE_ID),
CONSTRAINT fk_student
FOREIGN KEY (STUDENT_ID) REFERENCES Students(STUDENT_ID),
CONSTRAINT fk_course
FOREIGN KEY (COURSE_ID) REFERENCES Courses(COURSE_ID));
INSERT INTO Departments VALUES
('BS','Buisnes','Dr.Eyal'),
('CH','Chemistry','Prof.Doron'),
('CS','Computer Science','Dr.Israel'),
('MT','Mathematics','Prof.Levi');
INSERT INTO Courses VALUES
('B-10','Marketing','CLASS',5,'BS'),
('B-40','Operations Res.','SEMIN',3,'BS'),
('C-200','Programing','LAB',4,'CS'),
('C-300','Pascal','LAB',4,'CS'),
('C-55','Data Base','CLASS',3,'CS'),
('M-100','Linear Algebra','CLASS',3,'MT'),
('M-200','Numeric Analyses','CLASS',3,'MT');
INSERT INTO Students VALUES
(105,'Moshe','Haifa'),
(107,'Eyal','Tel Aviv'),
(110,'Ran','Haifa'),
(200,'David','Tel Aviv'),
(210,'Dan','Tel Aviv'),
(240,'Ayelet','Tel Aviv'),
(245,'Yoel','Haifa'),
(310,'Tova','Jerusalem');
INSERT INTO Grades VALUES
(105,'B-40','WIN1999','B',70,70),
(105,'C-200','AUT1999','A',90,85),
(105,'C-55','SUM1998','A',58,70),
(105,'M-100','SUM1998','B',75,50),
(200,'B-10','AUT1999','A',70,65),
(200,'C-200','AUT1999','B',78,50),
(200,'M-100','SUM1998','B',90,90),
(210,'B-10','WIN1999','A',78,50),
(210,'C-200','AUT1999','A',85,80),
(210,'M-100','AUT1999','A',90,90),
(245,'B-10','AUT1999','A',80,70),
(245,'B-40','WIN1998','A',85,95),
(245,'M-100','AUT1999','A',90,80),
(310,'M-100','SUM1998','A',65,100);
Now what I'm trying to do is to print all course names and student names where their grade multiplied by 1.1 is bigger than semester grade.
Now, I manage to do it by printing the course_id and student_id but then on this result I'm trying to connect between the student_id and their names in order to actually print the student name (s_name) and course name instead (course_id)
this is the current script I have:
SELECT STUDENT_ID,COURSE_ID
FROM Grades
WHERE (Grade*1.1>GRADE_SEM)
so basically all I want is quite the same results as I get but to have
student name (s_name) and course_name instead their id's. (this is the print I get right now
Actually it's simple Join Can do that
SELECT
Students.S_Name, Courses.Course_Name,
Students.Student_ID, Courses.Course_ID
FROM
Grades
INNER JOIN Students on Students.Student_ID = Grades.Student_ID
INNER JOIN Courses on Courses.Course_ID = Grades.Course_ID
WHERE
(Grades.Grade*1.1>Grades.GRADE_SEM)
You can read Join more in here Join Documentation
You can see here for Demo = Demo

Joining multiple tables + HAVING clause

I have 4 tables :
create table Hotel (
numHotel int primary key,
nomHotel varchar(30),
ville varchar(30),
etoiles tinyint
);
create table Chambre (
numChambre int identity primary key,
numHotel int foreign key references Hotel(numHotel),
etage tinyint,
prixnuit smallmoney not null check (prixnuit>=100)
);
create table Client (
cinClient varchar(10) primary key,
nom varchar(30),
prenom varchar(30),
adresse varchar(255) default 'non renseignée',
telephone varchar(10) check (telephone like '0%' and len(telephone)=10)
);
create table reservation (
numReservation int identity primary key,
numChambre int foreign key references Chambre(numChambre),
numCl varchar(10) foreign key references Client(cinClient),
dateArrivee date,
dateDepart date,
constraint ck_dates check ((Datediff(day,dateArrivee,dateDepart)>0))
);
Column names are French, but I think they're understandable.
So the question is : I need to select the names of Hotels (nomHotel) having achieved a total price higher than a certain price (e.g. 10000)
This is what I did on paper :
select nomHotel from Hotel h join Chambre ch on h.numHotel=ch.numChambre join reservation r on ch.numChambre=r.numChambre
group by nomHotel
having COUNT(r.numChambre)*ch.prixnuit>10000
And (of course) I got it wrong.
Any Help is appreciated, Thanks.
translations : "prixnuit" is the room's (chambre) price per night.
The total revenue (I think) is based on the number of reservations.
I'm thinking you need to calculate the number of nights per reservation, no?
So, maybe:
select nomHotel,
sum(Datediff(day,r.dateArrivee,r.dateDepart)*ch.prixnuit)
from Hotel h join Chambre ch on h.numHotel=ch.numChambre join reservation r
on ch.numChambre=r.numChambre
group by nomHotel
having sum(Datediff(day,r.dateArrivee,r.dateDepart)*ch.prixnuit)>10000
select nomHotel, sum(Datediff(day,dateArrivee,dateDepart) * prixnuit)
from Hotel h join Chambre ch on h.numHotel=ch.numHotel
join reservation r on ch.numChambre=r.numChambre
group by nomHotel
having sum(Datediff(day,dateArrivee,dateDepart) * prixnuit)>1000

SQL double primary key, many-to-many relationship

I'd like to connect 3 tables. In one of them I must use a compound primary key. I know, how to deal with single. I have the following tables to connect:
CREATE TABLE Med_list
(
ID_med_list INT IDENTITY(200001,1) ,
No_med_list INT,
ID_med INT REFERENCES Med(ID_med),
PRIMARY KEY(ID_med_list, No_med_list)
)
CREATE TABLE Med
(
ID_med INT IDENTITY(3001,1) PRIMARY KEY ,
Name VARCHAR(20)
)
CREATE TABLE Visit
(
ID_Visit INT IDENTITY(600001,1) PRIMARY KEY,
ID_patient INT REFERENCES Patients(ID_patient),
Visit_date Datetime,
ID_med_duty INT,
No_med_list INT
)
I would like to every patient could have more than one medicine during one visit. I don't know how to connect table Visit and Med_list the way acceptable to SQL Server.
Thank you in advance for every hint or help:)
You need a many to many relation, if Med_list is supposed to be this relation (medicine to visits) then you are only missing one foreign key that points to the visit so the tables relation looks like this
Patient. <--- Visit. <--- Med_list. ---> Meds
The tables like this:
CREATE TABLE Med_list
(
ID_med_list INT IDENTITY(200001,1) ,
No_med_list INT,
ID_med INT REFERENCES Med(ID_med),
ID_Visit INT REFERENCES Visit(ID_Visit)
PRIMARY KEY(ID_med_list, No_med_list)
)
CREATE TABLE Med
(
ID_med INT IDENTITY(3001,1) PRIMARY KEY ,
Name VARCHAR(20)
)
CREATE TABLE Visit
(
ID_Visit INT IDENTITY(600001,1) PRIMARY KEY,
ID_patient INT REFERENCES Patients(ID_patient),
Visit_date Datetime,
ID_med_duty INT,
No_med_list INT
)
And your query can look like this
Select * From patients p
Join Visit v on v.ID_Patient = p.ID_Patient
Join Med_list ml on ml.ID_Visit = v.ID_Visit
Join Med m on m.ID_med = ml.ID_med
You could try this
I am also new in many-to-many relationship query.
SQLFiddle Example
SELECT
P.name,
M.Name
FROM
med_list ML
LEFT JOIN med M ON m.ID_med=ML.ID_med
LEFT JOIN visit V ON V.ID_Visit=ML.ID_Visit
LEFT JOIN patients P ON P.ID_patient=V.ID_patient