简体   繁体   中英

SQL Query for three tables with calculation

I was given an interview question and I cannot resolve it. I'm not in the SQL field, and it was more to show problem solving ability than SQL ability. I'd still like to figure it out though!

It was in MS SQL server, but a generic SQL answer is acceptable.

I have 3 tables: Sales, Customers, Products and NO NULL values in the tables.

Customers : Customer_ID, Customer_Name

Products : Product_ID, Product_Price

Sales : Customer_ID, Product_ID, Number_Purchased

They want me to display, the client who has paid the most, to the client who has paid the least.

So I need to link the Customer ID from Customers to the Customer ID in Sales and then the sales to the product price and work out Price * Number Purchased and assign it to the correct person.

I tried something like this at the time: (obviously wrong)

SELECT Customers.Customer_ID, Customers.Customer_Name, SUM(Sales.Number_Purchased *Products.Product_Price) as Total
FROM (Customers 
INNER JOIN Products 
ON Customers.Customer_ID = Products.Customer_ID)
INNER JOIN Sales ON 
Products.Product_ID = Sales.Product_ID
GROUP BY Customers.Customer_ID, Customers.Customer_Name

Obviously I'm not good with SQL but if somone can give me a shove in the right direction to solving this (second Interview is in a few hours!) I would really appreciate it! I've gotten myself tied in knots.

If you want the list sorted from paid the most to paid the least, add:

ORDER BY SUM(Sales.Number_Purchased * Products.Product_Price) DESC

Additionally, you have to change some of the JOIN conditions, since you are not establishing the correct connection between the tables.

And since you are doing this in MS-ACCESS, you have to wrap the JOINS with parenthesis

It should be:

SELECT Customers.Customer_ID, 
       Customers.Customer_Name,
       SUM(Sales.Number_Purchased * Products.Product_Price) AS Total
FROM ((Customers 
INNER JOIN Sales ON Sales.Customer_ID = Customers.Customer_ID)
INNER JOIN Products ON Sales.Product_ID = Products.Product_ID)
GROUP BY Customers.Customer_ID, Customers.Customer_Name
ORDER BY SUM(Sales.Number_Purchased * Products.Product_Price) DESC

I'd prefer to approach this question in the following steps.

First of all, find out the total of each purchase done by all the customers.

SELECT Customer_ID, SUM (Sales.Number_Purchased * Products.Product_Price)
FROM Sales
INNER JOIN Products ON Products.Product_ID = Sales.Product_ID
GROUP BY Customer_ID

Then we would like to know the customer name. So we will inner join the Customes table.

SELECT Customer_ID, Customer_Name, SUM (Sales.Number_Purchased * Products.Product_Price)
FROM Sales
INNER JOIN Products ON Products.Product_ID = Sales.Product_ID
INNER JOIN Customers ON Customers.Customer_ID = Sales.Customer_ID
GROUP BY Customer_ID

Finally, you can do a ORDER BY statement to find out the ones who paid the most and the least.

Take note that in your code, Products.Customer_ID is not allowed because Customer_ID is not one of the columns in the Products table.

EDIT Oops, there is an ambiguous column in my second SQL. It should be "SELECT Customers.Customer_ID" because the column name Customer_ID is used in two different tables.

Boy have I been in your shoes, half the time not allowed to normalize tables in a DB :(

Any who i've quickly looked so forgive the syntax errors. but you will get the idea:

SELECT Customers.Customer_ID, 
    Customers.Customer_Name, 
    SUM(Sales.Number_Purchased *Products.Product_Price) as Total
FROM Customers
LEFT JOIN SALES
ON customers.customer_ID = Sales.Customer_ID
left JOIN Products
ON  Sales.productid = products.product_ID
Customers.Customer_ID, Customers.Customer_Name
GROUP BY Customers.Customer_ID, Customers.Customer_Name
ORDER BY SUM(Sales.Number_Purchased * Products.Product_Price) DESC

Cant check it but basically you were right but not on joins.

Inner join will only get matching results. But what about users who haven't brought anything? They wont exist in the sales part so they wont exist in your results, which in the job i was in was a bad thing as they want see all customers. This allows you to pull back all of them, and then if you need to, filter out the null sales. Usually its best to zero value them, you can then provide information on customers who haven't spent. (added info makes them happy ;) )

SO, use a left join, you will get every customer regardless of spend. match that up then to the products remember you want to keep all sales, and making sure there isnt a problem with missing data, use another left. then really just use an order by, and done.

hope this helps

There are two things you missed. A) Links between tables are incorrect. Following the key columns is useful exercise B) As Filipe pointed out the ORDER BY clause does the sorting

SELECT 
  Customers.Customer_ID, Customers.Customer_Name, 
  SUM(Sales.Number_Purchased *Products.Product_Price) as Total
FROM Customers 
  -- connect sales to customers
  INNER JOIN Sales ON 
    ON Sales.Customer_ID = Customers.Customer_ID
  -- connect products to sales
 INNER JOIN Products 
   Products.Product_ID = Sales.Product_ID
-- group to deliver an aggregate
GROUP BY Customers.Customer_ID, Customers.Customer_Name
-- sort
ORDER BY SUM(Sales.Number_Purchased * Products.Product_Price) DESC

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM