I am working on issue, and cannot resolve it.
I have five tables:
t_employee = {employee_id_pk, fullname, phone, position, passport}
t_facility = {facility_id_pk, direction, title}
t_employee_facility = {emp_fac_id_pk, employee_id_fk, facility_id_fk}
this table is #ManyToMany relationship
between 't_employee' and 't_facility'
t_transport = {transport_id_pk, type}
t_trip = {trip_id_pk, trip_code, employee_id_fk, transport_id_fk}
this table is #ManyToMany relationship between 't_employee' and 't_transport'
And I want to get unique rows
I tried something like this
SELECT
employee_id, fullname, passport, phone, position, direction, title,
trip_code
FROM
t_facility
INNER JOIN t_employee_facility USING (facility_id)
INNER JOIN t_employee USING (employee_id)
INNER JOIN t_trip USING (employee_id)
GROUP BY
employee_id,
facility_id,
trip_code
There are 8 uniquie rows.
But the above example gives me 18, when I remove trip_id I get 8 rows, but
in this case I get repeating trip_code values for each employee_id.
I want to extract only not repeating rows. I guess that, I should do it using INNER JOIN, but I'm not sure.
Is it possible to join all this tables ?
thank you
Regards
It can be achieved using nested join query as follow:
SELECT B.employee_id, employee_id, fullname, passport, phone,
position,direction, title, trip_code
FROM (SELECT A.employee_id, employee_id, fullname, passport, phone,
position,direction, title
FROM (SELECT employee_id, direction, title FROM t_facility
JOIN t_employee_facility
ON t_facility.facility_id = t_employee_facility.facility_id
) AS A
JOIN employee ON A.employee_id = employee.employee_id) AS B
JOIN t_trip ON B.employee_id = t_trip.employee_id;
the INNER JOIN keyword selects should have matching values in both tables.
Ex :
SELECT id_pk,information,about
FROM information
INNER JOIN employe ON information.id_pk= employe.id_employe;
So yes, you can join your table when declare it each table.
If you only want the rows to be unique but it is OK, that some employees show more than one facility or trip, you may use the DISTINCT keyword.
SELECT DISTINCT
employee_id,
fullname,
passport,
phone,
position,
direction,
title,
trip_code
FROM t_facility
INNER JOIN t_employee_facility
USING (facility_id)
INNER JOIN t_employee
USING (employee_id)
INNER JOIN t_trip
USING (employee_id);
There are many unclear things in your question, still I'm posting whatever I have figured-out.
First of all I cannot see the table t_employee in FROM clause so I'm not sure this query will work. To get the column values for fullname, passport, phone, position you need to add the relevant table t_employee into FROM clause.
I'm not pretty sure about the JOIN syntax, you can check the MySQL JOINs syntax here.
SELECT
employee_id, fullname, passport, phone, position, direction, title,
trip_code
FROM
t_employee
INNER JOIN t_facility USING (facility_id)
INNER JOIN t_employee_facility USING (facility_id)
INNER JOIN t_employee USING (employee_id)
INNER JOIN t_trip USING (employee_id)
GROUP BY
employee_id,
facility_id,
trip_code
If this still doesn't work, you can try doing SELECT DISTINCT to get unique records, see the syntax here.
Related
I have got three tables:
In my project, there are several courses. A user is able to add a course to the dashboard. I am trying to display these courses in the dashboard. In that case, I don't know how to query it. userclasses is a table that contains user and a course user chose.
UPD:
userId is a foreign key referencing to users.id and classId is a foreign key referencing to classes.id
To expand upon Roslan's first example, for using JOINs within the FROM clause where the joins should exist, need to JOIN the tables so that you can get the related data based on the foreign keys:
SELECT uc.id, u.name, u.email, u.password, u.status,
c.name, c.short_description, c.long_description
FROM userclasses uc
INNER JOIN classes c ON uc.classId = c.id
INNER JOIN users u ON uc.userId = u.id
ORDER BY uc.id, u.name, c.name;
For some academia, the use of table aliases (such as the uc, u and c in the above example) might not be allowed. In this case, one simply has to specify all table references instead, where there may be ambiguous column names (same name, found in more than 1 table of the combined join) such as id and name:
SELECT userclasses.id, users.name, email, password, status,
classes.name, short_description, long_description
FROM userclasses
INNER JOIN classes ON userclasses.classId = classes.id
INNER JOIN users ON userclasses.userId = users.id
ORDER BY userclasses.id, users.name, classes.name;
No worries though, learning joins was a big hurdle for me way back when I first started learning SQL too, and at a time when comma-separated tables in the FROM clause was more common. To some, foreign key's (FK) are a tough concept to learn as well, but once one realizes that a FK is simply nothing more than a reference to some other table's id, this quickly becomes no big deal.
I think this method is just fine:
SELECT * FROM classes INNER JOIN (users, userclasses) ON (users.id = userclasses.userId and classes.id = userclasses.classId);
You can use joins. For example,
select uc.id, u.name, u.email, u.password, u.status,
c.name, c.short_description, c.long_description
from userclasses uc, classes c, users u
where uc.classid = c.id and uc.userid = u.id
order by uc.id, u.name, c.name;
OR:
SELECT * FROM userclasses
LEFT JOIN (classes, users)
ON (classes.id = userclasses.classId
AND users.id = userclasses.userId)
I have the following:
SELECT id, name, job_id, job_type, job_name, updated_at
FROM
(SELECT service.id,service.service_name FROM services as service
INNER JOIN positions p ON service.id = p.service_id
) As Tab1
INNER JOIN
(SELECT job.job_id, job.job_type, job.job_name, job.updated_at
FROM jobs as job
INNER JOIN positions p ON job.id = p.job_id
) AS Tab2
How can i remove duplicates created by INNER JOIN i tired with DISTINCT but its not working correct.
positions Table has only two rows this table is my middle table:
INSERT INTO `positions` (`id`, `service_id`, `job_id`) VALUES
(1, 440, 25),
(2, 439, 63);
You made a sbselect of the second inner join, and the join with the subselect has no join cirteria
SELECT id, name, job_id, job_type, job_name, updated_at
FROM
(SELECT service.id,service.service_name FROM services as service
INNER JOIN positions p ON service.id = p.service_id
) As Tab1
INNER JOIN -- this join has no join cirteria
(SELECT job.job_id, job.job_type, job.job_name, job.updated_at
FROM jobs as job
INNER JOIN positions p ON job.id = p.job_id
) AS Tab2
You don't need the subselects in the first place, try somthing like
SELECT service.id, service.name, job_id, job_type, job_name, updated_at
FROM
services as service
INNER JOIN positions p ON service.id = p.service_id
INNER JOIN jobs as job ON job.id = p.job_id
The problem is that you are joining the two subquery tables with no clause (ON field1 = field2).
You are pulling the id from the first table and the other fields from the second, with no connecting clause between the table. That is why you are getting partially duplicated data.
You need to add the joining clause between the tables.
I am not going to assume that you can do so logically by joining on the job_id, as was previously suggested. This would require that the two tables share specific job_ids. Of course, if this is true, then you just add the ON tab1.job_id = tab2.job_id and you should not see the same duplicated data.
You did not provide the data from the other tables, so I cannot tell if you would still get duplicates, as it would depend on if the same job_id appears in the tables more than once. To clear that up, you can do a DISTINCT or GROUP BY on all the fields to make the results unique. The fact that you said you tried distinct seems to confirm that you need the joining clause.
If you cannot join by job_id as it does not logically link the two tables, you will need to provide more logic into what you think the data should look like.
Here's my question. I'm just not even sure where I should start.
List the first name, last name, and title of each employee, as well as the first name, lastname, and title of their supervisor; employees without supervisors should have null for theirsupervisor values. Alias only the columns for the supervisor toSuperFirst,SuperLast,andSuperTitle; columns should be ordered asFirstName,LastName,Title,SuperFirst,SuperLast, andSuperTitle.
Here's the ER Diagram:
What is the question here? Please provide a clear question for us to work with.
Example Below for reference.
LEFT Join return all Employees all results that have a supervisor and ones that don't. The ones that don't would have a NULL value in the "S.*" columns. That should accomplish what you need.
SELECT FirstName, LastName, Title, S.FirstName AS SuperFirst, S.LastName AS SupertLast, S.Title AS SuperTitle
FROM dbo.Employee E
LEFT JOIN dbo.Employee S ON E.ReportsTo = S.EmployeeID
You are looking for a self-join on Employee Table as below as it references itself.
SELECT emp.FirstName
,emp.LastName
,emp.Title
,super.FirstName as SuperFirst
,super.LastName as SuperLast
,super.Title as SuperTitle
FROM employee emp
LEFT JOIN employee super ON emp.reportsto = super.EmployeeId
ORDER BY 1
,2
,3
,4
,5
,6;
Left join will put null in Supervisor columns if no matching values are retrieved.
Like mentioned before, when LEFT JOIN you should be able get NULL when there is no match. This code should work!
SELECT Employee.FirstName, Employee.LastName, Employee.Title, Emp.FirstName AS SuperFirst, Emp.LastName AS SuperLast, Emp.Title AS SupperTitle
FROM Employee LEFT JOIN Employee AS Emp ON Employee.ReportsTo = EmployeeTwo.EmployeeId
Table 1 :- tbl_contacts
Fields
user_id
contact_id
first_name
last_name
Table 2 :- tbl_phone_details
Fields
contact_id
phone_number
phone_type
Table 3 :- tbl_email_details
Fields
contact_id
email_address
email_type
QUERY -
SELECT
tbl_contacts.*, tbl_email_details.*, tbl_phone_details.*
FROM
tbl_contacts, tbl_email_details,
tbl_phone_details
WHERE
tbl_contacts.user_id = '1'
I want to get first_name, last_name, Phone and Email details of particular user_id. I have used above query but its giving me repeated results and I am having less knowledge on DB queries like JOIN and INNER QUERY.
If anyone has any idea, please kindly help.
OUTPUT NEEDED:-
contact_id, first_name, last_name, phone_number, phone_type, email_address, email_type
(Here email and phone number can have 1 or more values for particular users).
Try like this
If you want to retrieve data for particular ID
SELECT T.contact_id,
T.first_name,
T.last_name,
P.phone_number,
P.phone_type,
E.email_address,
E.email_type
FROM tbl_contacts T LEFT JOIN tbl_phone_details P ON
T.contact_id = P.contact_id
LEFT JOIN tbl_email_details E ON
T.contact_id = E.contact_id
WHERE T.contact_id = #contact_id
If you want to retrieve all data
SELECT T.contact_id,
T.first_name,
T.last_name,
P.phone_number,
P.phone_type,
E.email_address,
E.email_type
FROM tbl_contacts T LEFT JOIN tbl_phone_details P ON
T.contact_id = P.contact_id
LEFT JOIN tbl_email_details E ON
T.contact_id = E.contact_id
SELECT tbl_contacts.*, tbl_email_details.*, tbl_phone_details.* FROM
tbl_contacts, tbl_email_details, tbl_phone_details WHERE
tbl_contacts.user_id = '1'
You forgot to mention the condition by which you are going to join all the tables!
SELECT c.first_name, c.last_name, p.phone_number, e.email_address
FROM tbl_contacts c, tbl_email_details e, tbl_phone_details p
WHERE tbl_contacts.user_id = '1'
AND c.contact_id = e.contact_id
AND e.contact_id = p.contact_id;
SELECT c.contact_id, c.first_name, c.last_name,
phone.phone_number, phone.phone_type,
email.email_address, email.email_type
FROM tbl_contacts c
LEFT JOIN tbl_email_details email ON c.contact_id = email.contact_id
LEFT JOIN tbl_phone_details phone ON c.contact_id = phone.contact_id
WHERE tbl_contacts.user_id = '1'
Sql queries are easy to learn and write and they are very useful in getting the important data from database. Joins are used to basically fetch the data from two or more tables on the bases of common column in both tables.
Inner Join will select those values that are common in both of the tables.
Left Join will select all the data from the left table and Right Join will select all the data from right table on the basis of id.
These are the basics of SQL and you must know how to fetch accurate data using them.
this is how I would make that request with JOIN ... but there might be some better or faster way to do it.
SELECT first_name, last_name, phone_number, email_address
FROM tbl_contacts
JOIN tbl_phone_details
ON tbl_contacts.contact_id=tbl_phone_details.contact_id
JOIN tbl_email_details
ON tbl_email_details.contact_id=tbl_contacts.contact_id
WHERE tbl_contacts.user_id = '1';
And just so you don't get lost in all the different answers here (which are probably all correct):
you don't need to give an aliase name to your tables (it's just for readability)
you don't need to mention the table names in your column list if the column name is unique (e.g first_name is only in tbl_contacts). Just if you want the contact_id then you should decide which one (e.g. tbl_phone_details.contact_id)
the multi-select as Jayaram proposed, is exactly the same as the JOIN. MySQL handles both queries the same way (I just didn't see his answer when I responded, sorry)
Let's say i have the following model:
Customer(customer_id (PK), firstName, lastName, email)
Item(item_id (PK), name, description)
Orders(orders_id (PK), customer_id (FK), item_id (FK), promotion_id (FK)),
Promotion(promotion_id (PK), date, gift_id (FK))
Gift(gift_id (PK), name, description)
Now, let's say that i have the following requirement:
Retrieve the list of all orders (not grouped by) from all customers and the name column from both the item and gift associated.
The difficult part is that the association table orders has a foreign key column to a one to many table (promotion) that, in his turn, has the foreign key to the gift;
I have the following query that worked, but i figure out that should have a more elegant way to approach the problem than doing a lot of joins like this:
select concat(c.firstName, ' ', c.lastName) as customerName,
i.name, g.name
from customer as c
left join orders as o on c.customer_id = o.customer_id
inner join item as i on o.item_id = i.item_id
inner join promotion as p on o.promotion_id = p.promotion_id
inner join gift as g on p.gift_id = g.gift_id;
How i could resolve the query in a more elegant way?
Thanks in advance!
I think this is perfectly elegant. Joins are very classy and often misunderstood.
You can drop the INNER keywords as joins are inner by default, and the AS keywords are optional; also because your column names are the same across the joins, you can simply use USING instead of ON:
SELECT CONCAT_WS(' ', c.firstName, c.lastName) customerName,
i.name, g.name
FROM customer c
LEFT JOIN orders o USING (customer_id)
JOIN item i USING (item_id)
JOIN promotion p USING (promotion_id)
JOIN gift g USING (gift_id)
Indeed, if those are the only columns having the same name across the joined tables one could go further and use NATURAL joins (although I don't like that as it hides what's going on if the schema changes):
SELECT CONCAT_WS(' ', c.firstName, c.lastName) customerName,
i.name, g.name
FROM customer c
NATURAL LEFT JOIN orders o
NATURAL JOIN item i
NATURAL JOIN promotion p
NATURAL JOIN gift g