MySQL Inner Join Against an Inner Join? - mysql

I have 3 tables "Employees", "EmployeeLeaveDays" and "EmployeeLeaves".
I'm looking to create a view that displays the date of the leave and the employee name. So in order for my calendar to work I have split everyones leave into individual days(EmployeeLeaveDays) which has an FK that links each day back to (EmployeeLeaves) which has other details around the leave, in EmployeeLeaves I have a column "employee" which is an FK back to employees which contains the name.
So In my view I want to return the name as you can see is 2 tables away, I've wrote this MySQL query but it doesn't work (returns no data), I'm wondering if there is anyway to do what I need to do?
SELECT
EmployeeLeaveDays.id,
EmployeeLeaveDays.employee_leave,
EmployeeLeaveDays.leave_date,
EmployeeLeaveDays.leave_type
FROM EmployeeLeaveDays
INNER JOIN EmployeeLeaves
ON EmployeeLeaveDays.employee_leave=EmployeeLeaves.employee
INNER JOIN Employees
ON EmployeeLeaves.employee=Employees.employee_id;
Hopefully from that you're able to see what I'm trying to achieve, how ever I've attached some screenshots of the table structure.
Thanks

After some thinking I got there in the end. Here's the final query.
SELECT
EmployeeLeaveDays.id,
EmployeeLeaveDays.employee_leave,
EmployeeLeaveDays.leave_date,
EmployeeLeaveDays.leave_type,
EmployeeLeaves.employee,
Employees.employee_id,
Employees.first_name,
Employees.last_name
FROM EmployeeLeaveDays
LEFT JOIN EmployeeLeaves ON EmployeeLeaveDays.employee_leave = EmployeeLeaves.id
LEFT JOIN Employees ON EmployeeLeaves.employee = Employees.id;

Related

Joining the same table twice in MYSQL

I am trying to create a MYSQL query that pulls in data from a range of tables. I have a master bookings table and an invoice table where I am recording invoice id's etc from Stripe.
I am storing two invoices per booking; one a deposit, the second the final balance.
In my admin backend I then display to the admin info on whether the invoice is paid etc so need to pull in data from SQL to show this.
I'm following some previous guidance here What's the best way to join on the same table twice?.
My query is returning data, however when the invoices table is included twice (to give me the deposit and balance invoices) however the column names are identical.
Could someone point me in the right direction? I think I need to somehow rename the columns on the second returned invoice??? Sorry new to anything but basic SQL queries.
This is my SQL
SELECT * FROM bookings
INNER JOIN voyages ON bookings.booking_voyageID = voyages.voyage_id
LEFT JOIN emailautomations ON bookings.booking_reference = emailautomations.automation_bookingRef AND emailautomations.automation_sent != 1
LEFT JOIN invoices ON bookings.booking_stripeDepositInvoice = invoices.invoice_id
LEFT JOIN invoices inv2 ON bookings.booking_stripeBalanceInvoice = inv2.invoice_id
Thanks to #Algef Almocera's answer I have amended my SQL (and stopped being lazy by using SELECT *, was able to trim loads of columns down to not many!)
SELECT
bookings.booking_status,
bookings.booking_reference,
bookings.booking_stripeCustomerReference,
bookings.booking_stripeDepositInvoice,
bookings.booking_stripeBalanceInvoice,
bookings.booking_totalPaid,
bookings.booking_voyageID,
bookings.booking_firstName,
bookings.booking_lastName,
bookings.booking_contractName,
bookings.booking_contractEmail,
voyages.voyage_id,
voyages.voyage_name,
voyages.voyage_startDate,
depositInvoice.invoice_id AS depositInvoice_id,
depositInvoice.invoice_status AS depositInvoice_status,
balanceInvoice.invoice_id AS balanceInvoice_id,
balanceInvoice.invoice_status AS balanceInvoice_status
FROM bookings
INNER JOIN voyages ON bookings.booking_voyageID = voyages.voyage_id
LEFT JOIN emailautomations ON bookings.booking_reference = emailautomations.automation_bookingRef AND emailautomations.automation_sent != 1
LEFT JOIN invoices depositInvoice ON bookings.booking_stripeDepositInvoice = depositInvoice.invoice_id
LEFT JOIN invoices balanceInvoice ON bookings.booking_stripeBalanceInvoice = balanceInvoice.invoice_id
This, sometimes, couldn't be avoided as keywords might actually often be the same but of different purpose per table. To help with that, you can use aliases. for example:
SELECT
invoices.column_name AS invoices_column_name,
transactions.column_name AS transactions_column_name
FROM invoices ...
LEFT JOIN transactions ...

How to create an Outer Join on 4 Tables to get all values Plus Count of 1 field

I have 4 tables which need to be joined. They are:
Contractors
Crews
Skill_type
Location
I also need to be able to count the number of contractors in each crew.
I have created some SQL (MySql) which does the job nicely:
Select contractors.crew_id as contractors_crew_id,
auburntree.crews.crew_name, count(*) as members, skill_type.skill,
location.location_name
FROM contractors
JOIN auburntree.crews on contractors.crew_id=crews.id
JOIN skill_type on skill_type.skill_id = crews.skill_id
JOIN location on location.id = crews.location_id
GROUP BY contractors.crew_id ;
The contractors table contains a foreign key reference to which crew they are assigned to. Hence the column "contractors_crew_id"
I get a nice result, as you can see in this screen capture image:
https://drive.google.com/file/d/0B5elaUk7GlRoS0JWblE3ZzFXY0E/view?usp=sharing
Problem Defined:
I need to define an empty crew first before I add contractors/members. I will give it a name, a skill and a location. I might define an empty crew several days in advance. Currently an empty crew does not show up in my results.
I want to see:
contractors_crew_id = Null, crew_name, skill_type, Location, members 0
I have tried using RIGHT OUTER JOIN on my tables and I still do not see empty crew. LEFT OUTER JOIN does not work either.
contractors_crew_id will be Null at that point, as no contractors have been assigned yet.
I Hope this makes, sense - sorry it is a bit long and complicated. I have tried really hard to explain in.
Many Thanks !!
Because you are actually focussing on information about crews, and not contractors, I would suggest to start by querying the crews table (in the FROM part of your query) and then join the other tables.
Using a LEFT JOIN on the contractors table should then give you the desired result. Since crews is now the "left" table in the query, the result will include all rows from crews, even when there is no corresponding contractor. This answer explains it very well.
This query works for me on test tables based on your examples:
SELECT
contractors.crew,
crews.crew,
COUNT(contractors.id) as members,
skills.skill,
locations.location
FROM crews
JOIN skills ON crews.skill = skills.id
JOIN locations ON crews.location = locations.id
LEFT JOIN contractors ON contractors.crew = crews.id
GROUP BY contractors.crew, crews.id;
To see for yourself, try this SQL Fiddle.
Try this, instead:
Select contractors.crew_id as contractors_crew_id, crews.crew_name, count(*) as members, skill_type.skill, location.location_name
FROM crews
LEFT OUTER JOIN contractors on contractors.crew_id=crews.id
LEFT OUTER JOIN skill_type on skill_type.skill_id = crews.skill_id
LEFT OUTER JOIN location on location.id = crews.location_id
GROUP BY contractors.crew_id ;
That should pull all crews, regardless of whether or not they have contractors assigned. The way you wrote your original query starts by looking at your contractors and then pulling in any crews they might be assigned to. Crews is clearly your focal table here, so you should be joining the rest of your tables to it, rather than to the contractors table.

In joins if specific column is null than in return resulting query does not retun a whole row

I am trying to get records from multiple tables. If "im.path" column is null in the db against the specific id, then in result whole row is skipped.
I want that if image does not exit against the specific id, then in result it shows the row with a image path column empty.
My query is below.
select distinct p.person_id as p_id,i.current_status,p.*, im.path from invitation i
join person p on i.person_id=p.person_id
join user u on p.person_id=u.person_id
join image im on u.user_id=im.entity_id
where sender_account_id=40 or i.person_id=40 and invitation_category_id=1
In this case if im.path column is empty, then whole record is skipped, that is what I do not want
Thanks in Advance.
SELECT distinct p.person_id as p_id, i.current_status, p.*, im.path
FROM invitation i
INNER JOIN person p on i.person_id=p.person_id
INNER JOIN user u
on p.person_id=u.person_id
LEFT join image im
on u.user_id=im.entity_id
WHERE (sender_account_id=40
or i.person_id=40)
and invitation_category_id=1
I'm also suspicious of not having ()'s around the OR statement here; so I added them.
also without knowing where sender and invitation_category_ID reside, they may limit the results inappropriatly from the left join. So what table are sender_account and invitation_category_ID in?
http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/ is a great link explaining join types.

Need Help writing a MySQL query

I have a database with customer information, orders, etc. I need to run a query that returns all customers who have not placed an order at all.
Relevant tables: login and orders
Relevant Columns: login.loginID, login.loginFirstName, login.loginLastName, login.loginEmailAddress AND orders.OrderuserID
So essentially - in psuedocode: compare table login, column loginID for matches in the orders table under orders.OrderUserID. If no match exists (as in no orders placed) then output the users First Name, Last Name and Email address.
I have been racking my brain but having some real issues with the language. I'm a big time N00B when it comes to SQL.
Basically it'll look like that:
SELECT l.login_id
FROM login l
LEFT JOIN orders o
ON l.login_id = o.login_id
WHERE o.login_id IS NULL
The key is using LEFT JOIN with WHERE ... IS NULL condition. In other words, you specifically look for the rows in login table that don't have any information 'extended' within orders table.
That's just a general description, but I hope it should be helpful in your process of constructing the big query specific to your case. )
select loginFirstName, loginLastName, loginEmailAddress
from login
where loginID not in
(select distinct OrderuserID from orders)
You can also do it with a left join:
select loginFirstName, loginLastName, loginEmailAddress
from login left join orders on loginID = OrderuserID
where OrderuserID is null
Not sure which will execute faster; give it a try. The first is easier to understand, IMHO.
EDIT: "select distinct" means "return me the set of unique values of the field". So, the subquery in the first SQL returns the set of users (their IDs) who do have orders. If a user has multiple orders, DISTINCT makes sure her ID is returned only once.
This should do it:
select *
from login l
left join orders o on l.loginId = o.OrderuserID
where o.OrderuserID is null
Try:
select login.loginFirstName, login.loginLastName, login.loginEmailAddress
FROM login
LEFT OUTER JOIN orders ON login.loginID = orders.OrderuserID
WHERE orders.OrderuserID IS NULL;
or something like that. I suspect the trick for a newer SQL user is the LEFT OUTER join. Without that specifier, a join will only return rows from the first table IF there are matches in the second. This way you get them all (and then filter out matches with the IS NULL phrase).
Though you should try first yourself and you could search on google first :):) .
Anyways you can use it in this way,
SELECT l.loginFirstName,l.loginLastName,
l.loginEmailAddress FROM login AS l LEFT JOIN orders as o
ON l.loginID = o.OrderuserID where OrderuserID is NULL

Missing record in a complex SELECT FULL JOIN statement

I created a SQL statement that should return the number of appointments receive by all salesmen. I work with 3 tables, Contract, Salesmen and Appointment, and I need to show how many appointments was received by each salesmen.
My problem is that although I use a Full Join the result doesn't show people who didn't receive any appointments. I found that there is a problem about constraint.
I took a look to Except, Intercept and Union option but none of those could solve my problem. Which other way could I use to get the full list of reps having or not received some appointments?
There is an example of the statement I used:
SELECT C.RepID, COUNT(A.AppID) AS AppAttrib, C.AppointmentPurchased, S.Name, S.FirstName
FROM Repartition.dbo.Contract C
FULL JOIN Repartition.DBO.Appointment A
ON C.RepID = A.RepID
LEFT JOIN Repartition.DBO.Salesmen S
ON S.RepID = C.RepID
GROUP BY C.RepID, V.Nom, S.Name, S.FirstName
Thanks for your help,
Antenor
Not knowing your table structure in detail, I'm just guessing here - but I think your query starts at the wrong place - you should start with the Salesmen table, and go from there. So basically, select those columns from the Salesmen table that you need, and then join in the other tables as needed.
Something like this:
SELECT
s.RepID, S.Name, S.FirstName,
COUNT(A.AppID) AS AppAttrib,
C.AppointmentPurchased
FROM
Repartition.dbo.Salesmen s
LEFT OUTER JOIN
Repartition.dbo.Contract c ON s.RepID = c.RepID
LEFT OUTER JOIN
Repartition.dbo.Appointment a ON s.RepID = a.RepID
GROUP BY
s.RepID, s.Name, s.FirstName