Redundant values in columns with aggregate function? - sql

SELECT
SUM(total_amt_usd),
sales_rep_id,
sales_reps.name AS salesman,
region.name AS regionname
FROM orders
JOIN accounts
ON orders.account_id = accounts.id
JOIN sales_reps
ON accounts.sales_rep_id = sales_reps.id
JOIN region
ON sales_reps.region_id = region.id
Are the three columns redundant with the SUM aggregate function? SUM I believe has correctly performed its operation of summing all the values (total_amt_usd) in the first column.

SELECT Sum(total_amt_usd),
sales_rep_id,
sales_reps.NAME AS salesman,
region.NAME AS regionname
FROM orders
LEFT JOIN accounts
ON orders.account_id = accounts.id
LEFT JOIN sales_reps
ON accounts.sales_rep_id = sales_reps.id
LEFT JOIN region
ON sales_reps.region_id = region.id
GROUP BY sales_rep_id,
sales_reps.NAME,
region.NAME

They do not look redundant. It seems like a query to find total sales amount summed separately for each sales representative from the orders table. The orders table has the sales representative id, which is used to lookup the representatives name from the joined sales_reps table and that table, in turn has a region_id which is used to look up region name from the joined region table. The final result has rows with id, name, and region of a sales representative along with total amount of orders that sales representative has got.
I think the query should be more like the following for this explanation to make sense:
SELECT
SUM(total_amt_usd),
sales_rep_id,
sales_reps.name AS salesman,
region.name AS regionname
FROM orders
JOIN accounts
ON orders.account_id = accounts.id
JOIN sales_reps
ON accounts.sales_rep_id = sales_reps.id
JOIN region
ON sales_reps.region_id = region.id
GROUP BY sales_rep_id;

Related

How to do a 3-table join with aggregate functions and a group by clause

I can't figure out how to do a 3-table join with aggregate functions and a group by clause.
I have 3 tables:
Products
id
...
Sales
id
product_id
sale_price
...
Punches
id
punchable_id
punchable_type
...
I want to get all of the products data together with its total number of sales, views, (each row in punches table represents a view) and the total revenue from a product.
I have the following query:
#products = Product.joins("INNER JOIN sales ON sales.product_id = products.id INNER JOIN punches ON sales.product_id = punches.punchable_id AND punches.punchable_type = 'Product'").group("products.id").select("products.*, SUM(sales.sale_price) as revenue, COUNT(sales.id) as total_sales_count, COUNT(punches.id) as views").distinct
However, this is giving me the wrong data for the aggregate functions. The numbers are very high (I think it's summing and counting the rows a bunch of extra times).
When I do the Inner Join query with the products table and only one other table (either the punches or sales table), the data is fine. It blows up whenever I do the 2 joins in one query.
Does anyone know what's wrong with the above and how to properly write the query?
You should join to punches directly with products.id = punches.punchable_id ..etc not via sales.product_id

SQL Server Left Join producing duplicates

I have 3 tables, Budgets, Income, and Expenses.
Budget table:
Income table:
Expenses table:
This is my SQL statement:
SELECT
Budgets.BudgetID, Budgets.BudgetName, Budgets.Username_FK,
Budgets.BudgetAmount, Budgets.SavePercentage,
Expenses.ExpensesID, Expenses.ExpensesAmount, Expenses.ExpensesCategory,
Income.IncomeID, Income.IncomeAmount, Income.IncomeCategory
FROM
Budgets
LEFT JOIN
Income ON Budgets.BudgetID = Income.BudgetID_FK
LEFT JOIN
Expenses ON Budgets.BudgetID = Expenses.BudgetID_FK
WHERE
BudgetName = '2019
And the results are as follows:
Based on my Income table, there is only 1 record tied to BudgetID = 3, but in the left join, it duplicates.
Ideally, I would want it to return "null" on the duplicates. How do I do this?
You have several rows in expenses per budgetID, so your join produces that many rows. I tend to suspect that the same situation could happen with income too.
If you want one row per budgetID, then one option is pre-aggregation and a left join (or outer apply). Say you want the total expense and income per budget, you would do:
select b.*, e.expenseAmount, i.amountAmount
from budgets b
left join (
select budgetID_FK, sum(expenseAmount) expenseAmount
from expenses
group by budgetID_FK
) e on e.budgetID_FK = b.budgetID
left join (
select budgetID_FK, sum(incomeAmount) incomeAmount
from income
group by budgetID_FK
) i on i.budgetID_FK = b.budgetID
Now you are grouping rows in the dependent tables by budgetID, so you can't see the other columns of these tables, such as incomeCategory or expenseCategory (which have multiple values per budgetID).
For budgetID 3 , you have 4 expenses( distinct expense IDs) of 50.00 in your expense table for the same user. I think what you would want is the total expenses of same category and budget ID i.e budgetID 3 in this case
SELECT
Budgets.BudgetID, Budgets.BudgetName, Budgets.Username_FK,
Budgets.BudgetAmount, Budgets.SavePercentage,
Income.IncomeID, Income.IncomeAmount, Income.IncomeCategory,
ex.ExpensesCategory,
ex.Total_ExpensesAmount,
FROM Budgets
LEFT JOIN Income ON Budgets.BudgetID = Income.BudgetID_FK
LEFT JOIN (Select BudgetID_FK, ExpensesCategory, SUM(ExpensesAmount) as Total_ExpensesAmount
FROM Expenses
GROUP BY BudgetID_FK, ExpensesCategory) ex ON Budgets.BudgetID = ex.BudgetID_FK
WHERE BudgetName = '2019'

Subquery amount not coming in full

I have this query:
Select I.Invoice_Number, PA.Invoice_Number, I.Line_Amount, PA.Invoiced_Amount
from XXX as PA
Left join (select Invoice_Number, Line_Amount from Invoices) as I
on PA.Invoice_Number = I.Invoice_Number
Group by PA.Invoice_Number;
Both should give me the same amount of cost (I.Line_Amount = PA.Invoice_Amount) per Invoice_Number, yet I.Line_Amount is only bringing the first row on the list, while PA.Invoiced.Number brings the sum of the cost on that Invoice.
I tried using sum(Line_Amount) within the subquery but all records come out as Null.
Is there a way for me to join both tables and make sure that the amounts per invoice match to the total amount of that invoice?
Thanks!!
If I understand you correctly (and you want to make sure that sum of Line_Amount in Invoices table is the same as Invoiced_Amount in XXX table) the second table should have invoice number and sum of amounts:
select I.Invoice_Number, PA.Invoice_Number, I.total, PA.Invoiced_Amount
from XXX as PA
left join (
select Invoice_Number, sum(Line_Amount) as total
from Invoices
group by Invoice_Number
) as I
on PA.Invoice_Number = I.Invoice_Number
You can try it here: http://sqlfiddle.com/#!9/d1d010/1/0

SQL 4 tables inner join pick up sum Nulls also?

I have 4 tables.... Employees, Customers, Orders and Order_Info. I am trying to inner join the 4 tables to sum up the order amounts and calculate the employees commission based on 7%. I am very close to solving this but I have one slight problem: I am not getting all of the employees because less are showing up than exist in my Employees table. This is how I currently have my query written:
SELECT Employees.lName, Employees.fName,
SUM(quantOrdered * costEach) AS ttl_orders_value,
(SUM(quantOrdered * costEach) * .07) AS Commission
FROM Customers
INNER JOIN Employees ON Customers.empNumber = Employees.empNumber
INNER JOIN Orders ON Customers.custNumber = Orders.custNumber
INNER JOIN Order_Info ON Orders.ordNumber = Order_Info.ordNumber
GROUP BY Employees.lName, Employees.fName
ORDER BY Employees.lName, Employees.fName
I wish to get all employees even if their commission and total sales equal zero, which I believe to be calculated from NULLS.
Any help improving my query would be greatly appreciated!
try this:
SELECT Employees.lName, Employees.fName,
SUM(ISNULL(quantityOrdered,0) * ISNULL(priceEach,0)) AS ttl_orders_value,
(SUM(ISNULL(quantOrdered,0) * ISNULL(costEach,0)) * .05) AS Commission
FROM Employees
LEFT JOIN Customers ON Customers.empNumber = Employees.empNumber
LEFT JOIN Orders
INNER JOIN OrderDetails ON Orders.ordNumber = OrderDetails.ordNumber
ON Customers.custNumber = Orders.custNumber
WHERE Employees.workTitle = 'Developer'
GROUP BY Employees.lName, Employees.fName
ORDER BY Employees.lName, Employees.fName
Note, I have changed INNER JOIN to LEFT JOIN only for Orders table because as you say Employees records should be there, they only may not have linked orders.
You may also need to wrap NULL priceEach, costEach, quantityOrdered and quantOrdered values with ISNULL([field_name], 0) to get proper results for those employees not having any orders.

Ambiguous outer join when Left join two tables but duplicate records when link all three

I have three tables:
Table1 - Customer profile
customer id
customer name
customer country
customer total sales
Table2 - Contract list
contract number
customer id
customer state
contract sales
business code
Table3 - Business index
business code
business type
Each customer has xxx amount of contracts, and each 'customer total sales' in Table1 equals to sum of the 'contract sales' in Table2 for that particular customer.
What I want to list is all customer name, each customer's total sales, country; also list each customer's state and business type.
My query tried to pull customer id, customer name, customer country, customer total sales from Table1 and customer state from Table2 and business type from Table3. But when I Left Join Table1.customer id-->Table2.customer id, and left join Table2.business code-->Table3.business type, it pull all data I wanted but there were xxx row of duplicate records for each customer.
Then, I attempt to find out what caused it by removing one join and changing the join properties. It pops up message for 'ambiguous outer join' when:
I remove either one of the join leaving only two tables linked with one Left join;
I change either one of the joins to either Right join or Inner join
In T-SQL:
As table Customer_profile and Contract_list both have customer_id column table alias should be used to avoid ambigous column name error. Also to remove duplicate records Distinct key word should be added.Following query should work:
select distinct cp.customer_id,
cp.customer_name,
cp.customer_country,
cp.customer_total_sales ,
cl.customer_state,
bi.business_type
from Customer_profile cp
left join Contract_list cl on cp.customer_id = cl.customer_id
left join Business_index bi on bi.business_code = cl.business_code ;