How to display an average in a temp table using data from two tables in postgres - sql

So I have two tables. one table is called Students and the other table is called Grades. I'm trying to figure out how to join both tables together using the students ID from STUDENTS and students id in GRADE to get their actually grade. With that information I want to be able to find the average of all those grades for that student to display their average in a temporary table.
This is my code so far using JavaScript.. Thanks if anybody can help.
const { Client } = require('pg');
const client = new Client({
host: 'localhost',
user: 'postgres',
database: 'xxx',
password : 'xxx',
port: xxx,
});
client.connect();
const createStudents = `
CREATE TABLE students (
name varchar,
id uuid NOT NULL,
email varchar,
age int
);
`;
client.query(createStudents, (err, res) => {
if(err){
console.error(err);
return;
}
console.log("Students have been successfully connected");
})
const createGrades = `
CREATE TABLE grades (
name varchar,
id uuid NOT NULL,
class varchar,
email varchar,
grade int
);
`;
client.query(createGrades, (err,res) => {
if(err){
console.error(err);
return;
}
console.log("Grades have been successfully connected");
client.end();
})

This is in need of a Foreign Key between grades and students. A simple design that I think achieves what you want:
CREATE TABLE students (
id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar NOT NULL,
email varchar,
age int
);
CREATE TABLE grades (
id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
student_id integer NOT NULL REFERENCES students ON UPDATE CASCADE,
class varchar NOT NULL,
grade int NOT NULL
);
Then the query:
SELECT
name, avg(grade) AS avg_grade
FROM
grades
JOIN
students
ON
grades.student_id = students.id
GROUP BY
students.id
The FOREIGN KEY eliminates the duplication of information in your original design e.g name and email in the grades table. It all ensures that a grade can only be entered for a student that exists in the students table. The GENERATED ALWAYS AS IDENTITY sets up an automatically incrementing field that can be used as the Primary Key instead of your design which had no declared PK. REFERENCES students will by default use students.id as the referenced column for the values entered in grades.student_id.

Related

Get true or false if Records present table having two foreign Key along with both table record

I do not have much experience in SQL. trying to work out query as below:
i have three table A,B and C. table C have foreign key from table A and table B.
table A => Employee details,
table B => Training Details,
table C => save which Employee has completed which training.
so need basically fetch Employee Name(All), Training Name(All), True if Emp. completed particular Training or else false.
select distinct innerEmp.EmployeeID, innerEmp.FirstName + ' ' + innerEmp.LastName as EmpName,
innerTrain.TrainingID, innerTrain.TrainingName
from tblEmployee innerEmp, tblTraining innerTrain
Above giving me first two column. but table tblEmployeeTraining (table C) how to get third column (True if Emp. completed particular Training or else false).
Example
create table student(
snum numeric(9,0) primary key,
sname varchar(30),
major varchar(25),
standing varchar(2),
age numeric(3,0)
);
create table class(
name varchar(40) primary key,
meets_at varchar(20),
room varchar(10),
fid numeric(9,0),
);
create table enrolled(
snum numeric(9,0),
cname varchar(40),
primary key(snum,cname),
foreign key (snum) references
student(snum),
foreign key (cname) references
class(name)
);
Result i expect below:
Please Help

How to update the nested tables in sql using gorm?

Here the code is written in Go. I am using two tables where one table has a foreign key that refers to the other table's primary key. Let's say I have a database as following struct defined:
type User struct{
ID uint `gorm:"primary_key;column:id"`
Name string `gorm:"column:name"`
Place place
PlaceID
}
type Place struct{
ID uint `gorm:"primary_key;column:id"`
Name string `gorm:"column:name"`
Pincode uint `gorm:"column:pincode"`
}
And the sql schema is:
create table place(
id int(20) NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL,
pincode uint(20) NOT NULL,
PRIMARY KEY (id),
)
create table user(
id int(20) NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL,
place_id uint(20) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (place_id) REFERENCES place(id)
)
Now while inserting in user by gorm as:
place := Place{Name:"new delhi",Pincode:1234}
user := User{Name: "sam", Age: 15, Place: place}
err = db.Debug().Create(&user).Error
//It inserts to both user and place table in mysql
//now while updating to name in user table as Samuel and place as
//following
place := Place{Name:"mumbai",Pincode:1234}
err = db.Debug().Model(&User{}).Where("id =?",
1,).Update(&user{Name:"Samuel",Place:place}).Error
It updates the row in user table but creates a new row in place table.But it should update the matching row in place table and not create a new one
Is there any way to do it? Here I am not using auto migrate function to create db tables.
The answer to your question should be sought in a relations or Association Mode.
The example below shows how to add new associations for many to many, has many, replace current associations for has one, belongs to
db.Model(&user).Association("Place").Append(Place{Name:"mumbai",Pincode:1234})
Or you can replace current associations with new ones:
db.Model(&user).Association("Place").Replace(Place{Name:"mumbai",Pincode:1234},Place{Name:"new delhi",Pincode:1234})
Probably It's creating a new row because you didn't set the ID on Place{Name:"mumbai",Pincode:1234}.

postgres insert multiple tables at once with generated columns

Suppose I have this piece of data (in reality roughly 5,000 entries every few seconds, initially 50,000 from a data dump):
[
"person": {
"name": "Johnny Bravo",
"location": {
"zipcode": 11111,
"address": "1 Second Ave"
},
"phone_numbers": [ 15007774321, 12227435432 ]
}
]
and this schema:
CREATE TABLE person(
id serial PRIMARY KEY,
name varchar(255) UNIQUE,
location_id integer NOT NULL REFERENCES location(id)
)
CREATE TABLE location(
id serial PRIMARY KEY,
zipcode integer NOT NULL,
address varchar(255) NOT NULL
)
CREATE TABLE phone_number(
id serial PRIMARY KEY,
"number" integer NOT NULL
)
CREATE TABLE person_number_relationship(
id serial PRIMARY KEY,
phone_number_id integer NOT NULL REFERENCES phone_number(id),
person_id integer NOT NULL REFERENCES person(id)
)
This is an oversimplification but the parts that matter are here. Currently to insert this data I use the language accessing the database (scala) to do most of the work.
Insert all locations and then select all locations (2 queries)
Replace location with location id in persons list
Insert phone numbers and then select all phone numbers (2 queries)
Create a map of phone number's number to id
Insert persons list and then select persons id and name (2 queries)
Create a map of person's name to id
Create a new list of person_id, phone_number_id from the phone_numbers list and the persons map
Insert the new list (1 query)
The question I am asking can be broken into two parts:
How can I insert into two tables where one table requires a generated id from the other?
How can I insert a many to many relationship for two tables when the ids are generated on insert?
Ideally I would like to push all of this logic down to the database where I wont be wasting memory sending extra information between the driver and the database

I do not know how to build a SQL query correctly

I work on my project using the sqlite database. In the project there is a chat, without channels, just 1 on 1. These are the tables:
db.run(`CREATE TABLE IF NOT EXISTS user (
id integer PRIMARY KEY AUTOINCREMENT,
firstName varchar(30),
lastName varchar(50),
email varchar(150),
phone varchar(12),
address varchar(255),
photo varchar(255),
hash varchar(255),
token varchar(255)
)`);
db.run(`CREATE TABLE IF NOT EXISTS chat (
id integer PRIMARY KEY AUTOINCREMENT,
lastMessage varchar(255)
)`);
db.run(`CREATE TABLE IF NOT EXISTS chatUser (
id integer PRIMARY KEY AUTOINCREMENT,
idChat integer,
idUser integer,
FOREIGN KEY (idChat) REFERENCES chat(id) ON DELETE CASCADE,
FOREIGN KEY (idUser) REFERENCES user(id) ON DELETE CASCADE
)`);
db.run(`CREATE TABLE IF NOT EXISTS message (
id integer PRIMARY KEY AUTOINCREMENT,
idChat integer,
idUser integer,
text varchar(255),
FOREIGN KEY (idChat) REFERENCES chat(id) ON DELETE CASCADE,
FOREIGN KEY (idUser) REFERENCES user(id) ON DELETE CASCADE
)`);
In the chatUser table, I always add only two users (the current user and the user with which it is rewritten). I'm trying to make a query to get a list of the current user's chat (list should include name, photo, chat id of the person whom chatting with me and last message)
db.all(`
SELECT chatUser.idChat,
user.firstName,
user.lastName,
user.photo,
chat.lastMessage
FROM user, chatUser, chat
WHERE user.id = chatUser.idUser
AND chat.id = chatUser.idChat
AND user.id != ?
`, [id], function(error, chats) {
...
}
Where id - current user id. This worked until I came from another user who, instead of one chat, displays two extra ones. Please help me build the query correctly.
You can imagine the query is splited into two steps :
You have to select the chats for the current user
From the chats of the current user you can select the other users participating in the same chats
Bellow example for the current user equals 1 :
SELECT othersChatUser.idChat,
user.firstName,
user.lastName,
user.photo,
chat.lastMessage
FROM
user,
chatUser as currentChatUser,
chatUser as othersChatUser,
chat
WHERE currentChatUser.idUser = 1
AND currentChatUser.idChat = othersChatUser.idChat
AND user.id = othersChatUser.idUser
AND user.id <> currentChatUser.idUser
AND chat.id = othersChatUser.idChat;
The result of your query : SQL Fiddle

How to do multiple inserts to SQL table with foreign key relationship safely with delete first insert if second insert fails

I have these tow tables:
CREATE TABLE cities (
city varchar(80) primary key,
location point
);
CREATE TABLE weather (
city varchar(80) references cities(city),
temp_lo int,
temp_hi int,
prcp real,
date date
);
I am using PostgreSQL with Knex JavaScript Driver
While doing an insert transaction, how can do i ensure that if i get an error in inserting in table weather after inserting in table cities, i can go back and delete the insert in table cities to ensure database integrity.
Please i just need a glimpse of what i can do.
Maybe I understood the questiong wrong, but it sounds like a basic case of using transactions. Just start transaction, do the inserts and if any of the inserts are failing rollback. With knex you can do it like this (http://knexjs.org/#Transactions):
knex.transaction(trx => {
return trx('cities')
.insert({
city: 'inari',
... rest of the fields ...
})
.then(() => {
return trx('weather').insert({
city: 'inari',
... rest of the fields ...
});
});
})
.then(() => {
console.log('inserted 2 rows');
})
.catch(err => {
console.log('one of the queries failed, no rows were inserted and transaction was rolled back')
});
You shouldn't be using triggers for this.
You can write AFTER INSERT trigger ON weather table.
As your city is primary key in cities table, when Insertion in weather table fails, you can delete entry from cities table using WHERE condition- city = NEW.city.
NEW.city indicates the value of city which was currently being inserted in weather table and insertion has been failed.