I am currently working on a small project that is meant to allow a user to create, read, update and delete employees, departments and locations from a SQL database.
I am having trouble with the LEFT JOIN function as I am not too experience with SQL. There are 3 databases:
Personnel,
Departments
Locations
They are organized like in the image attached.
I am trying to create a table for the user to view all Departments and their locations, however I am having trouble with this. I am assuming I need to use LEFT JOIN for this but I am struggling to make it work.
Any help would be greatly appreciated.
Thank you,
Liam
I have tried the following:
'SELECT d.id, d.name as departmentName, l.name as locationName from department d, LEFT JOIN location l ON (l.id = d.locationID)'
the issue doesn't seem to be complicated at all, you were on good track - I've recreated your DB in SSMS and your query worked just fine once I removed the unnecessary coma before the 'LEFT JOIN'. This way you will get the departments without any location set too since you're using LEFT JOIN.
If you want to create a view out of this data just add 'CREATE VIEW view_name AS' before the query.
CREATE TABLE personnel (
id INT IDENTITY(1,1) PRIMARY KEY,
firstName VARCHAR(255),
lastName VARCHAR(255),
jobTitle VARCHAR(255),
email VARCHAR(255),
departmentid int
);
CREATE TABLE department (
id INT IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(255),
locationId INT
);
CREATE TABLE location (
id INT IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(255)
);
INSERT INTO location (name)
values
('Los Angeles'),
('Paris')
INSERT INTO department (name, locationId)
values
('Finance LA',1),
('HR LA',1),
('IT LA',1),
('Finance Paris',2),
('HR Paris',2),
('IT Paris',2)
INSERT INTO personnel (firstName, lastName, jobTitle, email, departmentId)
VALUES
('Joe', 'Bean', 'xxxx','xxx#xxx.com', 1),
('Jake', 'Blake', 'xxxx','xxx#xxx.com', 2),
('Chloe', 'Kashew', 'xxxx','xxx#xxx.com', 3),
('John', 'Cena', 'xxxx','xxx#xxx.com', 4),
('Matt', 'Hard', 'xxxx','xxx#xxx.com', 5),
('Paris', 'Hilton', 'xxxx','xxx#xxx.com', 6),
('Donald', 'Duck', 'xxxx','xxx#xxx.com', 1),
('Kyle', 'Hilton', 'xxxx','xxx#xxx.com', 2),
('Cart', 'Kashew', 'xxxx','xxx#xxx.com', 3),
('John', 'Blake', 'xxxx','xxx#xxx.com', 4),
('Cart', 'Hard', 'xxxx','xxx#xxx.com', 5),
('Matt', 'Hilton', 'xxxx','xxx#xxx.com', 6),
('Kyle', 'Duck', 'xxxx','xxx#xxx.com', 1),
('Matt', 'Bro', 'xxxx','xxx#xxx.com', 2),
('John', 'Man', 'xxxx','xxx#xxx.com', 3)
SELECT d.Id AS departmentId, d.Name AS departmentName, l.Name AS locationName FROM department d LEFT JOIN location l ON d.locationId = l.id
Related
I'm trying to achieve something in Laravel/MySQL and cannot seem to be pointed in the right direction for a solution. I can achieve what I am looking for with subqueries, but I have been told they are not as efficient as joins. And, I'm going to have to convert the solution for this into Eloquent/Query Builder, and the way I have it working with subqueries and unions doesn't seem to convert easily.
What I am trying to do is select one row from two possible tables, based on the created_at date of the row. I want to join this created_at value with my users table as a new column called started_at. Here is some sample data and how I can achieve the query with a subquery/union of the two possible tables that I can get the data from:
CREATE TABLE users (
id INTEGER,
first_name TEXT,
last_name TEXT
);
INSERT INTO users (id, first_name, last_name)
VALUES
(1, 'Craig', 'Smith'),
(2, 'Bill', 'Nye'),
(3, 'Bloop', 'Blop');
CREATE TABLE old_activity (
id INTEGER,
user_id INTEGER,
firm_id INTEGER,
amount INTEGER,
created_at DATE
);
INSERT INTO old_activity (id, user_id, firm_id, amount, created_at)
VALUES
(1, 1, 3, 5.24, '2019-04-29'),
(2, 2, 7, 4, '2019-03-28'),
(3, 3, 4, 6.99, '2019-04-28');
CREATE TABLE new_activity (
id INTEGER,
user_id INTEGER,
firm_id INTEGER,
plays INTEGER,
saves INTEGER,
created_at DATE
);
INSERT INTO new_activity (id, user_id, firm_id, plays, saves, created_at)
VALUES
(1, 1, 3, 10, 1, '2019-04-27'),
(2, 2, 3, 12, 2, '2019-03-29'),
(3, 3, 3, 6, 3, '2019-04-27');
CREATE TABLE firms (
id INTEGER,
name TEXT
);
INSERT INTO firms (id, name)
VALUES
(1, 'apple'),
(2, 'banana'),
(3, 'orange');
select
id,
first_name,
last_name,
(select created_at from old_activity
where user_id = users.id
union
select created_at from new_activity
where user_id = users.id
order by created_at asc
limit 1) as started_at
from users
The query should only return the oldest created_at for a particular user in one of the two activity tables.
How can I achieve this with a join? Any help with this would be greatly appreciated.
Hmmm . . . You could always use window functions:
select u.*, a.*
from users u left join
(select a.*,
row_number() over (partition by a.user_id order by a.created_at desc) as seqnum
from ((select oa.* from old_activity oa) union all
(select na.* from new_activity na)
) a
) a
on a.user_id = a.id and a.seqnum = 1
Schemas
// First table
CREATE TABLE assignments (
id int,
uid int,
comments varchar(255),
assignmentdate date,
status int
);
INSERT INTO assignments (id, uid, comments, assignmentdate, status)
values (1, 6, 'a', '2019-07-15', 0), (2, 6, 'ab', '2019-07-15', 0),
(3, 6, 'abc', '2019-07-14', 0), (4, 6, 'abc', '2019-07-14', 1)
, (5, 7, 'xyz', '2019-07-14', 1), (6, 7, 'zyx', '2019-07-14', 1);
// Second table
CREATE TABLE users (
id int,
username varchar(255),
status int
);
INSERT INTO users (id, username, status)
values (6, 'user1', 0), (7, 'user2', 0),
(8, 'user3', 1);
// Third table
CREATE TABLE user_images (
id int,
uid int,
imagename varchar(255),
status int
);
INSERT INTO user_images (id, uid, imagename, status)
values (1, 6, 'abc.jpeg', 0), (2, 6, 'def.jpeg', 0), (3, 8, 'ghi.png', 1);
what I'm looking for here is to get
1) distinct and latest row of table assignments which,
2) joins the table users and get a row and then joins,
3) distinct and latest row of table user_images.
So far i have gone through this answer
My trial query:
SELECT
p.*,
u.username,
groupedpi.*
FROM
assignments p
INNER JOIN(
SELECT
comments,
MAX(id) AS latest
FROM
assignments
WHERE
STATUS
= 0
GROUP BY
uid
) AS groupedp
ON
groupedp.latest = p.id
LEFT JOIN users u ON
p.uid = u.id AND u.status = 0
LEFT JOIN(
SELECT
uid,
MAX(id) AS latesti,
imagename
FROM
user_images us
WHERE
STATUS = 0
GROUP BY
uid
order by id desc LIMIT 1
) AS groupedpi
ON
groupedpi.uid = p.uid
Output:
The 3rd result I'm not getting, i.e I'm not getting the distinct and latest record of the third table while joining.
Instead of abc.jpeg, I want to get def.jpeg.
MySQL is tripping you up here, because it automatically adds columns to GROUP BY if they aren't specified, so it's grouping the groupedpi subquery on imagename too - this will lead to duplicated rows. Remove the imagename column from the subquery (and the order by clause is irrelevant too) and have it just output the userid and the max image id
If you want the image name, join the images table in again on images.id = groupedpi.latesti (In the main query not the subquery that is finding the latest image id)
(Note that your screenshot says lastesti 2 but imagename abc- it's not the right pairing. ID 2 is def.jpg. When you want latest Id but also other data from the same row you can't do it in one hit unless you use an analytic (mysql8+) - you have to write a subquery that finds the max id and then join it back to the same table to get the rest of the data off that row)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I need to create a database but I'm not getting the correct logic.
It's like a story but I don't have any other way to explain it.
The scene is:
There are three entities; City, Books and Library.
I have to perform a task in which I will get CityId and Array of BookIds as input and I have to throw the LibraryNames based on following criteria:
The Library should be in the given City.
The Library should have all the books.
I have two input types
First for City (It will Provide me a single CityName or CityId)
and
Second is for Books (It will provide an array which consists of multiple BookIds or multiple BookNames).
If it is hard to understand then please discuss with me I will try to clear the concept.
It is a serious concern of me.
try this:
create table City
(
Id int,
Name varchar(50)
);
insert into City (Id, Name)
VALUES
(1, 'Toronto'),
(2, 'Chicago')
create table Libraries(
Id int,
Name varchar(50),
CityId int
);
insert into Libraries (Id, Name, CityId)
VALUES
(1, 'Toronto Library 1', 1),
(2, 'Toronto Library 2', 1),
(3, 'Chicago Library 1', 2),
(4, 'Chicago Library 2', 2)
create table Books(
Id int,
Isbn varchar(12),
LibraryId int
);
insert into Books (Id, Isbn, LibraryId)
Values
(1, '1234567891', 1),
(2, '13344555', 1),
(3, 'x123sada', 1),
(4, 'xasdsadas', 2),
(5, 'axxzksda', 2)
select DISTINCT b.Name
from Books a
inner join Libraries b
on a.LibraryId = b.Id
where Isbn in ('1234567891', '13344555')
and b.CityId = 1
Edit:
or 4NF:
create table City
(
Id int,
Name varchar(50)
);
insert into City (Id, Name)
VALUES
(1, 'Toronto'),
(2, 'Chicago')
create table Libraries(
Id int,
Name varchar(50),
CityId int
);
insert into Libraries (Id, Name, CityId)
VALUES
(1, 'Toronto Library 1', 1),
(2, 'Toronto Library 2', 1),
(3, 'Chicago Library 1', 2),
(4, 'Chicago Library 2', 2)
create table Books(
Id int,
Isbn varchar(12),
);
insert into Books (Id, Isbn)
Values
(1, '1234567891'),
(2, '13344555'),
(3, 'x123sada'),
(4, 'xasdsadas'),
(5, 'axxzksda')
create table LibraryBooks
(
LibraryId int,
BookId int
);
insert into LibraryBooks (LibraryId, BookId)
VALUES
(1, 1),
(1, 2),
(3, 1),
(2, 4),
(5, 2)
select DISTINCT c.Name
from Books a
inner join LibraryBooks b
on a.Id = b.BookId
inner join Libraries c on
c.Id = b.LibraryId
where Isbn in ('1234567891', '13344555')
and c.CityId = 1
You could structure it like this: (Three tables)
City:
Id, Name
Id = unique number
Library:
Id, Name, LiesInCity
Id = unique number
LiesInCity = The city Id the library lies in.
Book:
Id, Name, LiesInLibrary
Id = number
LiesInLibrary = The library Id the book is in.
Then you would SELECT the book list you had, and check if they are all in that Library. (You would also check if the Library is in the right City)
Note: You would need to have multiple Book entries if a book is in multiple Library's
I have a table called leaders. in it I have id,userid,bmid,reps,rounds,ts. Basically I need to put the top ten unique users out of the table that have the most rounds. Now each time someone enters their reps,rounds its as a pair so someone might have 12 rounds 13 reps so if that is their max and it is within the top ten of all users then I need to pull that info plus their corresponding reps. I thought I had this but it is actually pulling their max rounds and their max reps from different rows. What I have is below.
SELECT max(l.rounds) as rounds, l.reps, m.name, l.userid
from leaders l
inner join members m on m.id = l.userid
where m.genre = 'male' and l.bmid = 1
group by l.userid
order by rounds desc,reps desc
the join is to the members table to get some info on them.
I guess you need a subquery to achieve this. Take a look at this:
How to select the first/least/max row per group in SQL
EDIT: Try this code: http://sqlfiddle.com/#!2/8bb81/3
CREATE TABLE `leaders` (
`id` int(11) AUTO_INCREMENT,
`userid` int(11),
`rounds` int(11),
`reps` int(11),
PRIMARY KEY (`id`)
);
INSERT INTO `leaders` (userid, rounds, reps) VALUES
(1, 5, 3), (1, 7, 2), (1, 7, 1), (1, 7, 8),
(2, 7, 6), (2, 7, 9), (2, 4, 3),
(3, 7, 2), (3, 3, 5),
(4, 8, 9);
SELECT
userid,
MAX(rounds) AS max_rounds, (
SELECT MIN(reps)
FROM leaders l2
WHERE l2.userid = l1.userid AND l2.rounds <> l1.rounds
) AS min_reps
FROM leaders l1
GROUP BY userid
ORDER BY max_rounds DESC, min_reps ASC;
I'm trying to join the NAME and PHOTO from USERS table to the TRANSACTIONS table based on who is the payer or payee. It keeps telling me can't find the table this -- What am I doing wrong?
SELECT `name`,`photo`,`amount`,`comment`,
(
CASE `payer_id`
WHEN 72823 THEN `payee_id`
ELSE `payer_id`
END
) AS `this`
FROM `transactions`
RIGHT JOIN `users` ON (`users`.`id`=`this`)
WHERE `payee_id`=72823 OR `payer_id`=72823
From the documentation about aliases:
The alias is used as the expression's column name and can be used in GROUP BY, ORDER BY, or HAVING clauses.
You can't use an alias in a join. You can use it only in the places listed above. The reason is that the alias is on a field in the result of the join. If the join were allowed to these aliases in its definition it would (or could) result in recursive definitions.
To solve your problem you could repeat the CASE clause in both places:
SELECT `name`,`photo`,`amount`,`comment`,
(
CASE `payer_id`
WHEN 72823 THEN `payee_id`
ELSE `payer_id`
END
) AS `this`
FROM `transactions`
RIGHT JOIN `users` ON `users`.`id`= (
CASE `payer_id`
WHEN 72823 THEN `payee_id`
ELSE `payer_id`
END
)
WHERE `payee_id`=72823 OR `payer_id`=72823
However I would probably rewrite this query as two selects and UNION them:
SELECT name, photo, amount, comment, payer_id AS this
FROM transactions
JOIN users ON users.id = payer_id
WHERE payee_id = 72823
UNION ALL
SELECT name, photo, amount, comment, payee_id AS this
FROM transactions
JOIN users ON users.id = payee_id
WHERE payer_id = 72823
Result:
'name3', 'photo3', 30, 'comment3', 3
'name1', 'photo1', 10, 'comment1', 1
'name2', 'photo2', 20, 'comment2', 2
Test data:
CREATE TABLE users (id INT NOT NULL, name NVARCHAR(100) NOT NULL, photo NVARCHAR(100) NOT NULL);
INSERT INTO users (id, name, photo) VALUES
(1, 'name1', 'photo1'),
(2, 'name2', 'photo2'),
(3, 'name3', 'photo3'),
(4, 'name4', 'photo4');
CREATE TABLE transactions (amount INT NOT NULL, comment NVARCHAR(100) NOT NULL, payer_id INT NOT NULL, payee_id INT NOT NULL);
INSERT INTO transactions (amount, comment, payer_id, payee_id) VALUES
(10, 'comment1', 72823, 1),
(20, 'comment2', 72823, 2),
(30, 'comment3', 3, 72823),
(40, 'comment4', 4, 5);
SELECT
th.id, th.coin_id, th.coin_family, cm.coin_id, cm.current_price
FROM
trnx_history th
JOIN
fmi_coins.coins_markets cm
ON
cm.coin_id=(CASE th.coin_family WHEN 1 THEN 1 ELSE 2 END)