Working with complicated joins in MySQL - mysql

Here is the schema of the database I'm working with - [redacted]
I'm trying to come up with 2 different queries for 2 different result sets -
Sales representatives with the highest sales
Sales representatives with the highest sales grouped by managerId
I've had some luck with the 1st query; this is what I came up with:
SELECT
SUM(`products`.`cost`) AS `Sale`
, `employees`.`firstName`
FROM
`d2dpro`.`sales_reps`
, `d2dpro`.`products`
INNER JOIN `d2dpro`.`employees`
ON (`sales_reps`.`employeeId` = `employees`.`employeeId`)
INNER JOIN `d2dpro`.`sold_products`
ON (`products`.`productId` = `sold_products`.`productId`)
INNER JOIN `d2dpro`.`sales`
ON (`sold_products`.`saleId` = `sales`.`saleId`) AND (`sales`.`salesCampId` = `sales_reps`.`saleCampId`)
GROUP BY `employees`.`firstName`;
With this query, I'm stuck with this error:
Error Code: 1054
Unknown column 'sales_reps.saleCampId' in 'on clause'
Any help with this query? And also for the 2nd one?

You are using one table (sales_reps) that is CROSS JOIN-ed with the INNER JOIN of the tables employees, sold_products and sales. To be able to reference sales_reps in that JOIN you should include it as inner join: (the FROM clause should look like this)
FROM `d2dpro`.`products`
INNER JOIN `d2dpro`.`employees`
ON (`sales_reps`.`employeeId` = `employees`.`employeeId`)
INNER JOIN `d2dpro`.`sold_products`
ON (`products`.`productId` = `sold_products`.`productId`)
INNER JOIN `d2dpro`.`sales`
ON (`sold_products`.`saleId` = `sales`.`saleId`)
INNER JOIN `d2dpro`.`sales_reps`
ON (`sales`.`salesCampId` = `sales_reps`.`saleCampId`)

Related

MySQL JOIN tables with COUNT values

I have the following tables in my database.I only listed the important columns which can be used for joining.
I need to get the following output
Currently I'm using two seperate queries for each COUNT value
For assigned licenses
select
products.id,products.name,COUNT(assigned_licenses.id)
from
deployment_users
inner join
assigned_licenses
on
deployment_users.id = assigned_licenses.deployment_user_id
inner join
products
on
assigned_licenses.id = products.id
and
deployment_users.customer_id = 10
group by
assigned_licenses.id
;
For total licenses
select
products.id,products.name,COUNT(total_licenses.id)
from
customers
inner join
total_licenses
on
customers.iccode = licenses.iccode
inner join
products
on
total_licenses.id = products.id
and
customers.id = 10
group by
total_licenses.id
;
Since there are more than a 1,000 products that need to be listed,I want to combine them into a single query.How can I do that?
Your specification leaves some room for interpretation (e.g. can a user have assigned licenses without total licenses? if yes my query will fail.) but I would go with this.
SELECT
products.id,
products.name,
Count(Distinct total_licenses.id) As CountTotalLicenses,
Count(Distinct assigned_liceses.deployment_users_id) As CountAssignedLicenses
FROM products
LEFT JOIN total_licenses ON total_licenses.products_id = products.id
LEFT JOIN customers ON customers.iccode = total_licenses.customers_iccode
LEFT JOIN assigned_licenses ON assigned_liceses.total_licenses_id = total_licenses.id
WHERE
customers.id = 10
GROUP BY
products.id,
products.name
For the future it would be awesome if you could paste code as code and not as an image. People cannot simple copy paste snippets of your code and have to type everything again...
Try joining Both of your query
SELECT * FROM (
(First Query) as assigned_licn
INNER JOIN
(Second Query) as total_licn
USING (id)
);

Getting info through 3 tables

I'm following the SQL tutorial from w3schools.
I want to get the value of all orders delivered by a shipper. I don't have any idea about how I can get these details as the info are in different tables and the INNER JOIN didn't worked for me.
Database: http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_groupby
By now, I managed to get the number of orders by each shipper.
SELECT Shippers.ShipperName,COUNT(Orders.OrderID) AS NumberOfOrders FROM Orders
LEFT JOIN Shippers
ON Orders.ShipperID=Shippers.ShipperID
GROUP BY ShipperName;
How could I get the value of those?
To bring the Price of a Product into your query you will need to join in tables OrderDetails to the Order table on the Orders.Id and then join in the Products table to the OrderDetail table on ProductID
SELECT Shippers.ShipperName,
COUNT(Orders.OrderID) AS NumberOfOrders,
Sum(Products.price * OrderDetails.Quantity) AS SumOfPrice
FROM Orders
LEFT JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID
LEFT JOIN OrderDetails ON ORders.OrderID = OrderDetails.OrderID
LEFT JOIN Products ON OrderDetails.ProductID = Products.ProductID
GROUP BY ShipperName;
I just stuck with LEFT JOIN here as your example used, but an INNER JOIN would work just as well and be more efficient.
The FROM clause of the SQL statement is one of the first parts of the SQL to run against your database. It establishes which tables we are grabbing information from and the relationship between those tables (using the ON keyword). So here we bring in 4 tables, and use the ON keyword to show the relationship between all of them using their respective IDs. Then we can add their fields to the SELECT portion of the SQL statement and aggregate where needed.
If you want the "sum" of the product prices, that would be very similar to what you already have. Note how you currently use the COUNT() function to get the count, you can use the SUM() function to get the total of any numeric column.
Something like this:
SELECT
Shippers.ShipperName,
COUNT(Orders.OrderID) AS NumberOfOrders,
SUM(Products.Price) AS PriceOfOrders
FROM
Orders
INNER JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID
INNER JOIN OrderDetails ON Orders.OrderID = OrderDetails.OrderID
INNER JOIN Products ON OrderDetails.ProductID = Products.ProductID
GROUP BY
ShipperName
Or perhaps the price also needs to be multiplied by the quantity in this calculation? Something like this:
SELECT
Shippers.ShipperName,
COUNT(Orders.OrderID) AS NumberOfOrders,
SUM(Products.Price * OrderDetails.Quantity) AS PriceOfOrders
FROM
Orders
INNER JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID
INNER JOIN OrderDetails ON Orders.OrderID = OrderDetails.OrderID
INNER JOIN Products ON OrderDetails.ProductID = Products.ProductID
GROUP BY
ShipperName
It's up to your understanding of the table structure and the data, really. But the concept is the same, grouping by a value and applying a calculation to the grouped values (count or sum).

SQL Unknown column, despite it definitely being there - SQL Error (1054)

I am having an issue with my sql, I am trying to display a user based of their age group, attaching the string along with the primary key, but i only want that one value to be shown
I believe it is something like this
SELECT users.gbpfid,
users.aid,
compresults.total,
agegroup.aid AS aid2
FROM compresults
INNER JOIN competitions
ON competitions.cid = compresults.cid
INNER JOIN agegroup
ON agegroup.aid = users.aid
INNER JOIN users
ON compresults.gbpfid = users.gbpfid
WHERE competitions.compdate = (SELECT competitions.compdate
FROM competitions
INNER JOIN compresults
ON compresults.cid =
competitions.cid
WHERE compresults.gbpfid = users.gbpfid
ORDER BY competitions.compdate DESC
LIMIT 1)
however this throws up this error
SQL Error (1054): Unknown column 'users.aid' in 'on clause'
Which i cannot make any sense
when i remove the
"on agegroup.aid = users.aid" from line 5
it displays the records, but for each aid
I am confused how it recognises the column without the inner join (specifying the connection) but when i do whole inner join of the agegroup table, it joins fine, but with all the records
any ideas? thanks
You are trying to join agegroups using users.aid before users table is even joined.
INNER JOIN competitions
ON competitions.cid = compresults.cid
INNER JOIN agegroup
ON agegroup.aid = users.aid
INNER JOIN users
ON compresults.gbpfid = users.gbpfid
As you can see you are truing to access users.aid before is joined. Change order of the joins to:
competitions -> users -> agegroup
This should work:
INNER JOIN competitions
ON competitions.cid = compresults.cid
INNER JOIN users
ON compresults.gbpfid = users.gbpfid
INNER JOIN agegroup
ON agegroup.aid = users.aid
You should be able to access users.aid now.
Hope this helps.
The cause of the isue is that joins are processed from left to right. In your code you have the following order:
INNER JOIN agegroup
ON agegroup.aid = users.aid
INNER JOIN users
So, in the ON agegroup.aid = users.aid you reference the users table before it is joined to the fray.
Change the order of the joins:
compresults -> competitions -> users -> agegroup

If row exist in a table then use another tables value in SQL

What i would like to archieve:
Getting the correct sum of the total amount of the orders that has been cancelled of user id 2002.
Some pre information:
I am having deals which that has its price in deals.price and its id in deals.ID
I then have orders with a foreign key to deals.ID
Running this SQL:
select SUM(deals.price), orders.* from orders
JOIN deals ON deals.ID = orders.deal_id
where orders.user_id = 2002
and orders.cancelled = 1
Works just fine.
Here is where i get stuck:
As an addition to deals, each deals has products with their own prices.
Table is called deal_products, deal_products.price hold the price and deal_products.product_id has the ID of it.
A order is attached to a deal product in another table called order_products, where order_products.product_id = deal_products.product_id
To sum up: I would like to do is including a if inside the above SQL.
If a order has a row in order_products, get the order_products.product_id and find the price in deal_products (price) and use this instead of deals.price when SUM()'ing.
If there is no row it should use deals.price.
How can this be archieved? To first look in another table if there is a entry, and then further look in to a third table and get a value to use?
You can use COALESCE + LEFT JOIN:
select SUM(coalesce(dp.price, d.price)), o.*
from orders o JOIN deals d ON d.ID = o.deal_id
LEFT JOIN order_products op on op.order_id = o.id
LEFT JOIN deal_products dp on op.product_id = dp.product_id
where o.user_id = 2002 and o.cancelled = 1
group by ...;
COALESCE function returns first not null operand
LEFT [OUTER] JOIN = [INNER] JOIN + all rows of the structure on the left side of the LEFT JOIN keyword, which don't match the ON clause in the right structure.

SQL Query for multiple tables (foreign keys involved)

I currently have 5 tables in MySQL database. Some of them share foreign keys and are interdependent of each other. I am trying to create a query that will show all the results side by side(major, course, semester, etc). The query I created query it is not displaying my desired results since I have not added the other tables. I am not sure how to implement the other tables. How can I modify the mysql-query to display all the results in order?
Query
select * from course left join major on course.id = majors.id left join majors on courses_major_xref.majors_id = majors.id
Try the following
SELECT * FROM course
INNER JOIN major_courses_xref ON course.id = major_courses_xref.course_id
INNER join majors ON major_courses_xref.majors_id = majors.id
INNER JOIN courses_semester_xref ON course.id = courses_semester_xref.course_id
INNER JOIN semester ON courses_semester_xref.semester_id = semester.id;
I think there is just some order of operations problems in your query, try:
SELECT * from course
LEFT JOIN major_course_xref
ON course.id = major_course_xref.courseID
LEFT JOIN major
ON major.id = major_course_xref.major_id
LEFT JOIN course_semester_xref
ON course.id = course_semester_xref.course_id
LEFT JOIN semester
ON course_semester_xref.semester_id = semester.id