SQL Sumation from Different Tables - sql

I would like some help on this matter.
I Have three tables.
Products Table,
Invoice Table,
Cash Table
Products Table has 2 Columns as follows (PID,BRAND)
Invoice Table has 2 columns as follows (PID,TOTALSALES)
Cash Table has 2 columns as follows (PID,TOTALSALES)
The PID's could have many different BRANDS.
for eg:
PID BRAND
1 TEST1
2 TEST2
3 TEST3
All the three tables are linked by the PID column.
i have many rows in the invoice and cash tables.
My problem is to Group the SUMMED values of the TOTALSALES in the INVOICE and CASH tables BRAND wise.
I tried using left joins but the summation value always increases when there are more than 2 table in the join.
Any help will be highly appreciated.

You can use union all and then aggregate the results from the two tables together:
select p.brand, sum(invoice_sales) as invoice_sales, sum(cash_sales) as cash_sales
from ((select pid, totalsales as invoice_sales, 0 as cash_sales
from invoice i
) union all
(select pid, 0, totalsales
from cash c
)
) ic join
product p
on ic.pid = p.id
group by p.brand;

summarise the data in the Invoice and Cash tables separately
SELECT
pr.BRAND, (ISNULL(Inv.TOTALSALES, 0.00) + ISNULL(Csh.TOTALSALES, 0.00)) TotalSales
FROM Products pr
LEFT JOIN (
SELECT
PID, SUM(TOTALSALES) TOTALSALES
FROM Invoice GROUP BY PID
) Inv ON Inv.PID = pr.PID
LEFT JOIN (
SELECT
PID, SUM(TOTALSALES) TOTALSALES
FROM Cash GROUP BY PID
) Csh ON Csh.PID = pr.PID
ORDER BY pr.BRAND

You need two separate sums for the results of joining the tables by PID values and you will need to group the records by BRAND
select sum(Invoice.TOTALSALES) as invoice_sales, sum(Cash.TOTALSALES) as cash_sales
from Products
join Invoice
on Products.PID = Invoice.PID
join Cash
on Products.PID = Cash.PID
group by Invoice.PID, Products.BRAND;
If you do not need to group by products, then just omit Invoice.PID from the group by.

another way to do it is by using subquerys
select p.*,
(select sum(i.TOTALSALES) from Invoice i where i.PID = p.PID) as TotalSalesInvoice,
(select sum(c.TOTALSALES) from Cash c where c.PID = p.PID) as TotalSalesCash
from Products p

Related

SQL 2 Rows into 1

Below is a SQL script to see how many customers purchased both products, as well as how many customers purchased either of the two products.
I would like to be able to return a result set with one column for the first product, one column for the second, one column for Count with Both, and one column for Count with Either.
Instead it returns a column for each of the counts and a single NULL column for the ProductID.
SELECT
COUNT(DISTINCT b.CustomerID) AS "Count with Both",
COUNT(DISTINCT c.CustomerID) AS "Count with Either",
b.ProductID
FROM
LocationCode z
LEFT JOIN
(SELECT DISTINCT ProductID, CustomerID
FROM LocationCode a
WHERE a.ProductID IN ('MP040') AND a.ProductID IN ('OG010')) b ON z.CustomerID = b.CustomerID
LEFT JOIN
(SELECT DISTINCT ProductID, CustomerID
FROM LocationCode b
WHERE b.ProductID IN ('MP040', 'OG010')) c ON z.CustomerID = c.CustomerID
GROUP BY
b.ProductID
If I understand correctly, you can use a self-join and aggregation. The following does what you want for all pairs of products:
with cp as (
select customerid, productid,
count(*) over (partition by customerid) as num_customers
from locationcode
group by customerid, productid
)
select cp1.productid, cp2.productid, cp1.cnt as cnt1, cp2.cnt as cnt2,
count(*) as both
from cp cp1 join
cp cp2
on cp1.customerid = cp2.customerid and
cp1.productid < cp2.productid
group by cp1.productid, cp2.productid, cp1.cnt, cp2.cnt ;
You can of course add where filters if you only want results for certain products.

SQL: How to group by with two tables?

I have the tables products and history and I need to group by name:
products = (id_product, name)
history = (id_history, id_product, amount)
I tried this SQL query but it isn't grouped by name:
SELECT
products.name,
sum(history.amount)
FROM history
INNER JOIN products ON history.id_product = products.id_product
GROUP BY
products.name,
history.amount,
history.id_history;
This is the result:
You should only be grouping by the attributes you need to be aggregated. In this case, you need only products.name.
SELECT
products.name,
sum(history.amount) AS [Amount]
FROM history
INNER JOIN products ON history.id_product = products.id_product
GROUP BY
products.name;
If you need to include products without history (assuming sum should be 0 instead of null in this case), then you can use an OUTER JOIN instead of INNER JOIN to include all products:
SELECT
products.name,
COALESCE(sum(history.amount), 0) AS [Amount]
FROM history
RIGHT OUTER JOIN products ON history.id_product = products.id_product
GROUP BY
products.name;
This is no answer, but too long for a comment.
For readability's sake the product table should be first. After all it is products that we select from, plus a history sum that we can access via [left] join history ... followed by an aggregation, or [left] join (<history aggregation query>), or a subselect in the select clause.
Another step to enhance readability is the use of alias names.
Join the table, then aggregate
select p.name, coalesce(sum(h.amount), 0) as total
from products p
left join history h on h.id_product = p.id_product
group by p.name
order by p.name;
Aggregate, then join
select p.name, coalesce(h.sum_amount, 0) as total
from products p
left join
(
select sum(h.amount) as sum_amount
from history
group by id_product
) h on h.id_product = p.id_product
order by p.name;
Get the sum in the select clause
select
name,
(select sum(amount) from history h where h.id_product = p.id_product) as total
from products p
order by p.name;
And as you were confused on how to use GROUP BY, here is an explanation: GROUP BY ___ means you want one result row per ___. In your original query you had GROUP BY products.name, history.amount, history.id_history saying you wanted one result row per name, amount, and id, while you actually wanted one row per name only, i.e. GROUP BY products.name.

Triple Table Join with Subtraction

I have 3 tables (production, sales, wastage)
All 3 tables have the columns: Product and Quantity
I need a query statement that will join all 3 tables in the following manner:production - sales - wastage Grouped by Product
Thanks in advance for the tips and tricks :)
Combine tables using left join, group by product and get total quantity by substracting values assuming that there can be no record for a given product within sales or wastage tables and then count them as 0.
select p.product, sum(p.quantity - coalesce(s.quantity,0) - coalesce(w.quantity,0)) as qty
from production p
left join sales s on p.product = s.product
left join wastage w on p.product = w.product
group by p.product
You can group each table individually and then [left] join them:
SELECT p.product, p_quantity - COALESCE(s_quantity, 0) - COALESCE(w_quantity, 0)
FROM (SELECT product, SUM(quantity) AS p_quantity
FROM production
GROUP BY product) p
LEFT JOIN (SELECT product, SUM(quantity) AS s_quantity
FROM sales
GROUP BY product) s ON p.product = s.product
LEFT JOIN (SELECT product, SUM(quantity) AS w_quantity
FROM wastage
GROUP BY product) w ON p.product = w.product

SQL Join 3 tables group sum

Products with Id-Prod , desc, date fields
ENTRIES with Id-Prod Quantity, Amount.
Sorties with Id-Prod Quantity, Amount.
I want to make a query which join the 3 tables on Id-Prod and grouping it and sum the quantity and Amount for each products them calculate the stock which is equal to sum quantityIn -Sum QUantityOut
Thank you
To join and sum with 1-N looks like this -- we need to do a sub query to get the sums before the left join and a coalesce to set nulls to 0.
SELECT P.ID-Prod,
COALESCE(E.s,0) AS IN-Q,
COALESCE(S.s,0) AS OUT-Q,
COALESCE(E.s,0) - COALESCE(S.s,0) AS Stock
FROM Products P
LEFT JOIN (SELECT ID-Prod, SUM(Quantity) AS s
FROM ENTRIES GROUP BY ID-Prod) E ON P.ID-Prod = E.ID-Prod
LEFT JOIN (SELECT ID-Prod, SUM(Quantity) AS s
FROM Sorties GROUP BY ID-Prod) S ON P.ID-Prod = S.ID-Prod
GROUP BY P.ID-Prod

SQL Join with SUM()

I have two Tables
Product Details(About Product)
Sale Order Details(What Price is sold, quantity of products sold per order).
I am trying to do Join on Table 1 and Table 2 which should give the all the product details and sum(Quantity), Sum(Price)
Problem Facing: There are some products in Table 1 which are never sold, and those rows are missing in the result set, but I want details for all the rows in Table 1 with rows of Products never purchased should be NULL or 'o'
Query I am Using:
select
P.*,
ISNULL((sum([Q.Quantity])),0),
ISNULL((sum([Q.Price])),0)
From Table1 P
Left Outer Join Table2 Q on P.Product_ID = Q.Product_ID
Please help me with any suggestions that would work for me
How about this one:
select
P.Product_ID,
ISNULL(sum([Q.Quantity]),0),
ISNULL(sum([Q.Price]),0)
From Table1 P
Left Outer Join Table2 Q
on P.Product_ID = Q.Product_ID
group by
P.Product_Id