sum of column returning double the value - mysql

I have the following SQL query:
SELECT s.name, s.learner_tag, s.guild_id, s.id, ifnull(sum(t.xp),0) as xp, ifnull(sum(a.ap),0) as ap, (ifnull(sum(t.xp),0)/1000+ifnull(sum(a.ap),0)/100) as level, g.name
FROM student s
INNER JOIN guild g ON g.id = s.guild_id
LEFT JOIN student_task t ON s.id = t.student_id
LEFT JOIN student_achievement a ON s.id = a.student_id
WHERE s.class_id = ".$realm_id."
GROUP BY s.name, s.learner_tag, s.guild_id, s.id, g.name
ORDER BY level DESC LIMIT 10";
However the query returns double the expected value for the ap column. There is only 1 record in the student_achievement table and the value is 25. However my query returns 50 as the value of sum(a.ap). If I edit the value, it still doubles. sum(t.xp) is working fine. Can anyone spot my mistake?
Table Structure:
CREATE TABLE student
(
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
name VARCHAR(64) NOT NULL,
guild_id INT,
class_id INT NOT NULL,
time_updated INT,
ap INT NOT NULL,
learner_tag VARCHAR(64) NOT NULL,
schoology_id INT NOT NULL,
enrollment_id INT NOT NULL,
FOREIGN KEY (guild_id) REFERENCES guild (id),
FOREIGN KEY (class_id) REFERENCES class (id)
);
CREATE TABLE student_achievement
(
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
student_id INT NOT NULL,
achievement_id INT NOT NULL,
time_added INT,
ap INT NOT NULL,
FOREIGN KEY (student_id) REFERENCES student (id),
FOREIGN KEY (achievement_id) REFERENCES achievement (id)
);
CREATE TABLE achievement
(
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
name VARCHAR(64) NOT NULL,
value INT NOT NULL,
repeatable TINYINT NOT NULL,
image_url VARCHAR(200) NOT NULL,
description VARCHAR(240) NOT NULL
);
CREATE TABLE task
(
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
name VARCHAR(64) NOT NULL,
max_xp INT,
schoology_id INT,
class_id INT NOT NULL,
processed TINYINT,
type VARCHAR(15) NOT NULL,
FOREIGN KEY (class_id) REFERENCES class (id)
);

Related

Nested query in a view is giving me CHECK OPTION on non-updatable view

CREATE VIEW Res_borrow
AS
SELECT *
FROM borrowing
WHERE mem_id IN (
SELECT mpd.mem_id
FROM (
SELECT mem_id, COUNT(*) AS no_curr_bks
FROM borrowing
WHERE borrowing.ret_date IS NULL
GROUP BY borrowing.mem_id
)Y
RIGHT JOIN mpd ON y.mem_id = mpd.mem_id
WHERE y.no_curr_bks < mpd.nob OR y.no_curr_bks IS NULL
)
WITH CHECK OPTION;
I tried to create such a view but i am getting error
Here is the schema of db
CREATE TABLE MEMBER
(
mem_id INT PRIMARY KEY,
NAME VARCHAR(100) NOT NULL,
pass VARCHAR(12) NOT NULL,
CHECK(CHAR_LENGTH(pass)>7),
ph_no CHAR(11) NOT NULL,
gender VARCHAR(10) NOT NULL,
CHECK(gender='Female' OR gender='Male'),
address VARCHAR(50) NOT NULL,
age INT NOT NULL,
email VARCHAR(50) NOT NULL,
pkg_id INT DEFAULT 0,
FOREIGN KEY (pkg_id) REFERENCES packages(pkg_id)
)
create table mpd --Member Package Details
(
mem_id int primary key foreign key references member(mem_id),
nob int not null default 2,
dur int not null default 14
)
create table borrowing
(
bor_id int primary key,
mem_id int foreign key references member(mem_id) not null,
book_id int foreign key references book(book_id),
iss_date date not null,
ret_date date
)

SQL Joining 4 tables, only selecting columns from 2

CREATE TABLE user (
userID INT AUTO_INCREMENT PRIMARY KEY,
accountTypeID INT NOT NULL,
userEmail VARCHAR(320) NOT NULL,
userPassword VARCHAR(32) NOT NULL,
userFirst VARCHAR(20) NOT NULL,
userLast VARCHAR(20) NOT NULL,
userPhone VARCHAR(10) NOT NULL,
lastAccess TIMESTAMP NOT NULL,
userRegistry DATE NOT NULL,
FOREIGN KEY (accountTypeID) REFERENCES accountType(accountTypeID));
CREATE TABLE participant (
participantID INT AUTO_INCREMENT PRIMARY KEY,
vehicleID INT NOT NULL,
userID INT NOT NULL,
eventID INT NOT NULL,
participantRegistry DATE NOT NULL,
paymentMethodID INT NOT NULL,
FOREIGN KEY (vehicleID) REFERENCES vehicle(vehicleID),
FOREIGN KEY (userID) REFERENCES user(userID),
FOREIGN KEY (eventID) REFERENCES event(eventID),
FOREIGN KEY (paymentMethodID) REFERENCES paymentMethod(paymentMethodID));
CREATE TABLE vehicle (
vehicleID INT AUTO_INCREMENT PRIMARY KEY,
makeID INT NOT NULL,
vehicleModel VARCHAR(20) NOT NULL,
vehicleYear VARCHAR(4) NOT NULL,
tshirtID INT NOT NULL,
clubID INT NOT NULL,
FOREIGN KEY (makeID) REFERENCES make(makeID),
FOREIGN KEY (tshirtID) REFERENCES tshirt(tshirtID),
FOREIGN KEY (clubID) REFERENCES club(clubID));
CREATE TABLE club (
clubID INT AUTO_INCREMENT PRIMARY KEY,
clubName VARCHAR(20) NOT NULL,
clubLogo BLOB);
$sql="SELECT U.userFirst, U.userLast, C.clubName FROM user AS U, club AS C
INNER JOIN participant AS P
on P.userID = U.userID
INNER JOIN vehicle AS V
on V.vehicleID = P.vehicleID
INNER JOIN club AS C
on C.clubID = V.clubID
ORDER BY C.clubName ASC";
We are trying to get all the clubs and all the members (first and last name) in each club.
The participant and vehicle tables are just needed to link the users table to the club table.
I know it is something simple the server we are using doesn't display sql errors and does not have phpmyadmin.
Thanks to maSTAShuFu, I came to the working result of.
SELECT U.userFirst, U.userLast, C.clubName FROM club AS C
INNER JOIN vehicle AS V
on C.clubID = V.clubID
INNER JOIN participant AS P
on V.vehicleID = P.vehicleID
INNER JOIN user AS U
on P.userID = U.userID
ORDER BY C.clubName ASC

Split MySQL and compare it

I have a problem that I don't know how to resolve it, I am a begginer in SQL.
I want to display the first name of all students that have the same FirstName as the teachers name, In the database the teacher's name is a single field but contains 2 logical fields ( FirstName and LastName)
This is my database format
CREATE TABLE Faculty (
Id INT NOT NULL PRIMARY KEY AUTO_INCREMENT
,NAME VARCHAR(50)
,Address VARCHAR(60)
,YearFounded YEAR
,Dean VARCHAR(50)
);
CREATE TABLE Specialty (
Id INT NOT NULL PRIMARY KEY auto_increment
,IdFaculty INT (11) NOT NULL
,NAME VARCHAR(50)
,FOREIGN KEY (IdFaculty) REFERENCES Faculty(Id)
);
CREATE TABLE Course (
Id INT NOT NULL PRIMARY KEY auto_increment
,IdSpecialty INT NOT NULL
,NAME VARCHAR(50)
,TeachingYear INT
,Semester INT
,Professor VARCHAR(50)
,< -- TEACHER
FOREIGN KEY (IdSpecialty) REFERENCES Specialty(Id)
);
CREATE TABLE Student (
Id INT NOT NULL PRIMARY KEY auto_increment
,< -- STUDENT
IdFaculty INT NOT NULL
,IdSpecialty INT NOT NULL
,CurrentYear INT
,StudyGroup VARCHAR(10)
,Semester INT
,Scholarship VARCHAR(2)
,FOREIGN KEY (IdFaculty) REFERENCES Faculty(Id)
,FOREIGN KEY (IdSpecialty) REFERENCES Specialty(Id)
);
CREATE TABLE StudentData (
Id INT NOT NULL PRIMARY KEY
,CNP CHAR(13)
,FirstName VARCHAR(30)
,LastName VARCHAR(30)
,Father VARCHAR(50)
,Mother VARCHAR(50)
,Address VARCHAR(200)
,Nationality VARCHAR(50)
);
CREATE TABLE Grade (
Id INT NOT NULL PRIMARY KEY auto_increment
,IdStudent INT NOT NULL
,IdCourse INT NOT NULL
,Grade INT
,ExamDate DATE
,FOREIGN KEY (IdStudent) REFERENCES Student(Id)
,FOREIGN KEY (IdCourse) REFERENCES Course(Id)
);
Considering that Course.Professor field contains the professor firstname and lastname, I would use this query :
select sd.FirstName from StudentData sd
LEFT JOIN Student s on sd.Id = s.Id
LEFT JOIN Specialty special on s.IdSpecialty = special.Id
LEFT JOIN Course c on special.Id = c.IdSpecialty
WHERE c.Professor = CONCAT(sd.FirstName, ' ', sd.LastName)
EDIT:
If you only want students that have the same FirstName (not lastname) as the professor and if the professor field contains values like "Jacques Dupont" (for example) where Jacques is FirstName and Dupont is LastName then try this (using SUBSTRING_INDEX function to get the professor's FirstName):
select sd.FirstName from StudentData sd
LEFT JOIN Student s on sd.Id = s.Id
LEFT JOIN Specialty special on s.IdSpecialty = special.Id
LEFT JOIN Course c on special.Id = c.IdSpecialty
WHERE SUBSTRING_INDEX(c.Professor,' ',1) = sd.FirstName

Error 1215 Can't add foreign key constraint

I've read several posts on this type of error (one of them was quite similar), but I haven't found one yet that resolves the error that I'm having with the foreign key. Since I can recreate the error, I think I have a pretty good idea of what it is. I am new to SQL, however, and I can't resolve the problem. Here's the code from the two affected tables:
create table artist (
artist_id int unsigned not null auto_increment,
first_name nvarchar(50) not null,
last_name nvarchar(50) not null,
about_artist nvarchar(550) not null,
start_of_event datetime,
end_of_event datetime,
item_id int unsigned not null,
user_id int unsigned not null,
last_modified timestamp,
primary key (artist_id),
foreign key (item_id) references
items (item_id),
foreign key (user_id) references
users (user_id)
);
create table items (
item_id int unsigned not null auto_increment,
artist_id int unsigned not null,
item_name nvarchar(50) not null,
item_description nvarchar(150) not null,
last_modified timestamp,
primary key (item_id),
foreign key (artist_id) references
artist(artist_id)
);
My item_id is item_id int unsigned not null, in the first table, but item_id int unsigned not null auto_increment, in the second table. The second table is the one where it is the primary key. I can't do two auto increments in one table, and if I reverse the order of the tables, the same thing happens with a different column. How can I resolve this? Thank you.
Thinking about my comment, I'm increasingly confident that the link table is the way you need to go.
create table artist (
artist_id int unsigned not null auto_increment,
first_name nvarchar(50) not null,
last_name nvarchar(50) not null,
about_artist nvarchar(550) not null,
start_of_event datetime,
end_of_event datetime,
user_id int unsigned not null,
last_modified timestamp,
primary key (artist_id),
foreign key (user_id) references
users (user_id)
);
create table items (
item_id int unsigned not null auto_increment,
artist_id int unsigned not null,
item_name nvarchar(50) not null,
item_description nvarchar(150) not null,
last_modified timestamp,
primary key (item_id)
);
create table artist_item (
artist_id int unsigned not null,
item_id int unsigned not null
foreign key (artist_id) references
artist(artist_id),
foreign key (item_id) references
items(item_id)
);
You could add an auto-increment field to artist_item, or have the two ID fields as a composite key.
With this, you can query for all items relating to an artist (e.g. one artist has several items):
select
*
from
artist_item join items on
artist_item.item_id = items.item_id
where
artist_item.artist_id = [ID]
or all artists related to an item (e.g. one item was worked on by several artists):
select
*
from
artist_item join artist on
artist_item.artist_id = artist.artist_id
where
artist_item.item_id = [ID]

How to link the tables mysql

I have 3 tables in my mysql database: student, progress and subject. When I try to select data:
SELECT progress.id, progress.mark, subject.pname FROM progress, subject WHERE progress.id_student = 1;
I get the following table:
id mark pname
1 5 Math
1 5 Physics
Table progress I only have one entry:
id mark id_student id_subject
1 5 1 1
How can I get student progress by student_id?
CREATE DATABASE students;
USE students;
CREATE TABLE student (
id int NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL,
address varchar(60) NOT NULL,
byear int NOT NULL,
eyear int NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE subject (
id int NOT NULL AUTO_INCREMENT,
pname varchar(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE progress (
id int NOT NULL AUTO_INCREMENT,
mark int NOT NULL,
id_student int NOT NULL,
id_subject int NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES student (id),
FOREIGN KEY (id) REFERENCES subject (id)
);
SELECT progress.id, progress.mark, subject.pname
FROM progress LEFT OUTER JOIN subject ON (progress.id_subject= subject.id)
WHERE progress.id_student = 1;
Try
SELECT progress.id, progress.mark, subject.pname
FROM progress, subject
WHERE progress.id_student = 1 AND progress.id_subject = subject.id;