1

I have following sample database schema

https://i.sstatic.net/EKNxY.jpg

enter image description here

I want:
A) All sales, group by Users.
B) Discounts, group by users.

I am using following queries:
FOR A:

    SELECT u.UserID, u.UserName, Sum(d.Quantity * i.Price) AS 'Sales'
FROM OrderDetails d
INNER JOIN Orders o ON o.OrderID = d.OrderID
INNER JOIN Item i ON i.ItemID = d.ItemID
INNER JOIN [User] u ON u.UserID = o.UserID
GROUP BY u.UserID, u.UserName

RESULT:
UserID UserName Sales
1 Mobeen 11060
2 Cashier 25960

FOR B:

    SELECT u.UserID, u.UserName, Sum(r.DiscountAmount) AS Discounts
FROM Receipt r
INNER JOIN Orders o ON o.OrderID = r.OrderID
INNER JOIN [User] u ON u.UserID = o.UserID
GROUP BY u.UserID, u.UserName

RESULT:
UserID UserName Discounts
1 Mobeen 50
2 Cashier 310

BUT Then I decided to combine both queries but now the problem is that I am getting different results. The query is as below:

    SELECT u.UserID,
    u.UserName,
    Sum(d.Quantity * i.Price) AS 'Sales',
    Sum(r.DiscountAmount) AS 'Discounts'
FROM OrderDetails d
INNER JOIN Orders o ON o.OrderID = d.OrderID
INNER JOIN Item i ON i.ItemID = d.ItemID
INNER JOIN [User] u ON u.UserID = o.UserID
INNER JOIN Receipt r ON r.OrderID = o.OrderID
GROUP BY u.UserID, u.UserName

Result:
UserID UserName Sales Discounts
1 Mobeen 2270 50
2 Cashier 25760 430

2 Answers 2

4

The problem is that you are summing along multiple dimensions. If you want to combine them, use subqueries:

select s.userID, s.userName, s.Sales, d.Discounts
from (SELECT u.UserID, u.UserName, Sum(d.Quantity * i.Price) AS 'Sales'
      FROM OrderDetails d
           INNER JOIN Orders o ON o.OrderID = d.OrderID
           INNER JOIN Item i ON i.ItemID = d.ItemID
           INNER JOIN [User] u ON u.UserID = o.UserID
           GROUP BY u.UserID, u.UserName
     ) s join
     (SELECT u.UserID, u.UserName, Sum(r.DiscountAmount) AS Discounts
      FROM Receipt r
           INNER JOIN Orders o ON o.OrderID = r.OrderID
           INNER JOIN [User] u ON u.UserID = o.UserID
       GROUP BY u.UserID, u.UserName
     ) d
     on s.userId = d.userId and s.userName = d.userName

I think what is happening is that you are multiplying the receipt records for each item. You need to be very careful when bringing together data naively using joins. For such aggregations, subqueries are your friend.

If you need to get all the rows (i.e., there may be mismatches on either side), switch the join to a full outer join and use:

select coalesce(s.userId, d.userId) as userId, coalesce(s.userName, d.userName) as userName, . . .
Sign up to request clarification or add additional context in comments.

2 Comments

+1 lol, I was just about to post an almost identical answer :)
@Gordon There is a slight mistake/typo in the post that d.Discount in main select should be d.Discounts
0

The inner join to receipts is probably excluding some orders (not all orders have receipts, right) and double counting others (one order may have many receipts?)

1 Comment

Yes in my current database, not all orders have receipt but in the real scenario (after deployment) all orders will be having one receipt. And to second point, no, one order may have only one receipt.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.