SQL Joining 4 tables, only selecting columns from 2 - mysql

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

Related

MySql SELECT with Joins and conditions statement

I have three tables
TABLE `courses` (
id int NOT NULL UNIQUE AUTO_INCREMENT,
title varchar(50) NOT NULL UNIQUE,
duration int NOT NULL,
theme varchar(50) NOT NULL,
students_quantity int NOT NULL,
PRIMARY KEY (id)
);
TABLE `users` (
id int NOT NULL UNIQUE AUTO_INCREMENT,
name varchar(50) NOT NULL,
email varchar(50) NOT NULL UNIQUE,
password varchar(50) NOT NULL,
status varchar(20) NOT NULL,
role_id int NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (role_id) REFERENCES `roles` (id)
);
TABLE `teachers_courses` (
teacher_id int NOT NULL,
course_id int NOT NULL,
PRIMARY KEY (teacher_id, course_id),
FOREIGN KEY (teacher_id) REFERENCES `users` (id),
FOREIGN KEY (course_id) REFERENCES `courses` (id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
How can I get get courses.* and users.name AS teacher for this course, and if I have not course_id and teacher_id for this course in teachers_courses I'll get 'none' in teacher?
Use JOIN to combine your data following primary key - foreign key path.
Function coalesce() would return the second argument, if the first one evaluates to NULL.
select c.*, coalesce(u.name, 'none') as teacher
from courses c
left join teachers_courses tc on c.id = tc.course_id
left join users u on tc.teacher_id = u.id
order by c.id
Since there can be multiple teachers for each course, the only case in which you would get 'none' as teacher value would be if there is no teacher assigned for a course (not even one). If there is more than one teacher, there will be as many rows in the output as there are teachers for each course, thus I included ORDER BY to sort the result properly.
If you need to view the data for only one course, include a WHERE condition like this:
-- ... Above SQL here ...
WHERE c.id = ?

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

Get tickets available with their price

I'm tyring to get this query, but I think all the joins and sub queries are getting me confused, and it uses every table in my database.
CREATE TABLE Zone(
name char(12) not null,
price_multiplier float not null default 1.0,
primary key (name)
);
CREATE TABLE Seat(
row_no char(3) not null,
zone_name char(12) not null,
primary key (row_no),
foreign key (zone_name)
references Zone(name)
);
CREATE TABLE Production(
title varchar(100) not null,
url varchar(30) not null unique,
base_price numeric(5,2) not null,
mins smallint default 90,
genre varchar(30),
description text,
primary key (title)
);
CREATE TABLE Performance(
id mediumint not null AUTO_INCREMENT,
date_time datetime not null unique,
title varchar(100) not null,
primary key (id),
foreign key (title)
references Production(title)
);
CREATE TABLE Booking(
ticket_no mediumint not null AUTO_INCREMENT,
row_no char(3) not null,
performance_id mediumint not null,
customer_name varchar(300) not null,
primary key (ticket_no),
foreign key (row_no)
references Seat(row_no),
foreign key (performance_id)
references Performance(id)
);
If I run this query I can get the already booked seats with all the information:
SELECT
b.customer_name,
b.row_no,
s.zone_name,
ROUND(P.base_price * z.price_multiplier, 2) as ticket_price,
p.title,
p.date_time
FROM
Seat s
JOIN Booking b
ON s.row_no = b.row_no
JOIN Performance p
ON p.id = b.performance_id
JOIN Production P
ON p.title = P.title
JOIN Zone z
ON z.name = s.zone_name
WHERE
s.row_no IN
(
SELECT
b.row_no
FROM
Booking b
WHERE
b.performance_id = :perfID
)
;
I figured it out
SELECT
s.row_no,
s.zone_name,
ROUND(z.price_multiplier *
(
SELECT
P.base_price
FROM
Production P
JOIN Performance p
ON P.title = p.title
WHERE
p.id = :perfID
)
, 2) as price
FROM
Seat s
JOIN Zone z
ON s.zone_name = z.name
WHERE
s.row_no NOT IN
(
SELECT
s.row_no
FROM
Seat s
JOIN Booking b
ON s.row_no = b.row_no
WHERE
b.performance_id = :perfID
)
Thanks for your help.

JOIN FOUR TABLES in mysql. Error in syntax

I need to join four tables in mysql.
My database structure:
DROP DATABASE IF EXISTS db_applicant;
CREATE DATABASE db_applicant
DEFAULT CHARACTER SET 'utf8'
DEFAULT COLLATE 'utf8_unicode_ci';
USE db_applicant;
--
-- TABLE: PROFESSION
--
CREATE TABLE PROFESSION (
PROFESSION_ID INT NOT NULL AUTO_INCREMENT,
PROFESSION_NAME VARCHAR(50) NOT NULL,
PRIMARY KEY (PROFESSION_ID)
);
--
-- TABLE: SUBJECT
--
CREATE TABLE SUBJECT (
SUBJECT_ID INT NOT NULL AUTO_INCREMENT,
SUBJECT_NAME VARCHAR(50) NOT NULL,
PRIMARY KEY (SUBJECT_ID)
);
--
-- TABLE: APPLICANT
--
CREATE TABLE APPLICANT (
APPLICANT_ID INT NOT NULL AUTO_INCREMENT,
PROFESSION_ID INT NOT NULL,
LAST_NAME VARCHAR(30) NOT NULL,
FIRST_NAME VARCHAR(30) NOT NULL,
ENTRANCE_YEAR INT NOT NULL,
PRIMARY KEY (APPLICANT_ID),
FOREIGN KEY (PROFESSION_ID) REFERENCES PROFESSION (PROFESSION_ID)
);
--
-- TABLE: APPLICANT_RESULT
--
CREATE TABLE APPLICANT_RESULT (
APPLICANT_RESULT_ID INT NOT NULL AUTO_INCREMENT,
APPLICANT_ID INT NOT NULL,
SUBJECT_ID INT NOT NULL,
MARK INT,
PRIMARY KEY (APPLICANT_RESULT_ID),
FOREIGN KEY (SUBJECT_ID)
REFERENCES SUBJECT (SUBJECT_ID),
FOREIGN KEY (APPLICANT_ID)
REFERENCES APPLICANT (APPLICANT_ID)
);
--
-- TABLE: SPECIALITY_SUBJECT
--
CREATE TABLE SPECIALITY_SUBJECT (
SP_SB_ID INT NOT NULL AUTO_INCREMENT,
PROFESSION_ID INT NOT NULL,
SUBJECT_ID INT NOT NULL,
PRIMARY KEY (SP_SB_ID),
FOREIGN KEY (PROFESSION_ID)
REFERENCES PROFESSION (PROFESSION_ID),
FOREIGN KEY (PROFESSION_ID)
REFERENCES PROFESSION (PROFESSION_ID),
FOREIGN KEY (SUBJECT_ID)
REFERENCES SUBJECT (SUBJECT_ID)
);
I need that output would be something like:
first_name (this column from table applicant), last_name (this column from table applicant), entrance_year (this column from table applicant), profession_name (this column from table profession), subject_name (this column from table subject), mark (this column from table applicant_result).
You can see, that i have related fields. But i need strong INNER QUERY.
For that, i create new table with structure:
CREATE TABLE APP(
ALL_ID INT NOT NULL AUTO_INCREMENT,
APPLICANT_ID INT NOT NULL,
SUBJECT_ID INT NOT NULL,
PROFESSION_ID INT NOT NULL,
APPLICANT_RESULT_ID INT NOT NULL,
PRIMARY KEY (ALL_ID),
FOREIGN KEY (SUBJECT_ID)
REFERENCES SUBJECT (SUBJECT_ID),
FOREIGN KEY (APPLICANT_ID)
REFERENCES APPLICANT (APPLICANT_ID),
FOREIGN KEY (PROFESSION_ID)
REFERENCES PROFESSION (PROFESSION_ID),
FOREIGN KEY (APPLICANT_RESULT_ID)
REFERENCES APPLICANT_RESULT (APPLICANT_RESULT_ID)
);
And my inner:
SELECT ap.ALL_ID, a.FIRST_NAME, a.LAST_NAME,
a.ENTRANCE_YEAR, p.PROFESSION_NAME s.SUBJECT_NAME, ar.MARK
FROM app ap
JOIN (applicant a, profession p, subject s, applicant_result ar)
ON ap.APPLICANT_ID = a.APPLICANT_ID
AND ap.SUBJECT_ID = s.SUBJECT_ID
AND ap.PROFESSION_ID = p.PROFESSION_ID
AND ap.APPLICANT_RESULT_ID = ar.APPLICANT_RESULT_ID;
But i have error:
[2015-09-19 10:08:52] [42000][1064] You have an error in your SQL
syntax; check the manual that corresponds to your MySQL server version
for the right syntax to use near '.SUBJECT_NAME, ar.MARK FROM app ap
JOIN (applicant a, profession p, subject s, a' at line 1
Don't you think, a comma ',' is missing here in select statement before s.SUBJECT_NAME?
SELECT ap.ALL_ID, a.FIRST_NAME, a.LAST_NAME,
a.ENTRANCE_YEAR, p.PROFESSION_NAME s.SUBJECT_NAME, ar.MARK

sum of column returning double the value

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)
);