Need MYSQL uquery solution - mysql

I have the folowing tree tables one is the stock_items with all the items in it. The stock_in has the stock movements in to the stock and stock_out has the out movements:
and I want to get such a query result:
could some one help me to make this query?

You want to select the stock items and join the in totals and out totals. Aggregate to get the totals. Outer join to get items with and without transactions. Use COALESCE to replace nulls with zeros.
select
s.barcode, s.item_name,
coalesce(si.total, 0) as amount_in,
coalesce(so.total, 0) as amount_out,
coalesce(si.total, 0) - coalesce(so.total, 0) as balance,
s.unit
from stock_items s
left join
(
select barcode, sum(amount) as total
from stock_in
group by barcode
) si on si.barcode = s.barcode
left join
(
select barcode, sum(amount) as total
from stock_out
group by barcode
) so on so.barcode = s.barcode
order by s.barcode;

You can join tables using the barcode column?
select * from stock_items
join stock_in on stock_items.barcode = stock_in.barcode
join stock_out on stock_items.barcode = stock_out.barcode
Just replace the * with a list of desired column names

Unleash the power of subqueries and then use subtraction to compute the total stock level.
Basically the strategy here is to:
Run one query to sum up the total stock in
Run another query to sum up the total stock out
Run a final query subtracting the summed values.
select *, (stock_in - stock_out) as total from (select
product_id pid,
product_name,
product_unit,
(select sum(stock_in) from stock_in where product_id=pid) as stock_in,
(select sum(stock_out) from stock_out where product_id=pid) as stock_out
from products) summed
SQL fiddle here: https://www.db-fiddle.com/f/v95qsALSfnm66HoQb6PqJ6/0

Related

Apparently my Subquery returns more than 1 row

So I want to find all items from the parts table for which the price is greater than or equal to the average price of the respective product line.
And I tried it wirh subquerys and Group by but my Subquery returns more than one row. Any Help?
select * from parts
where price >= (select distinct avg(price)
from parts group by productLine)
You have to create a connection between the parts table and the average prices query, because as you have your subquery now, it returns the average price for all productlines, which you most probably you have more than one ... And also the DISTINCT doesn't help here, unless all of your productlines have the extact same AVG(price) -- which is quite unlikely.
With newer versions of mysql you can use a common table expression
with prices(avgprice, productline) as (
select avg(price), productline
from parts
group by productline)
select pa.*
from parts pa inner join prices pr on pa.productline = pr.productline
where pa.price >= pr.avgprice
If you are on a older version of mysql, which doesn't support CTE, you can also join on the result of a subquery
select pa.*
from parts pa inner join (
select avg(price) as avgprice, productline
from parts
group by productline) pr on pa.productline = pr.productline
where pa.price >= pr.avgprice
or you can just limit your subquery on the respective productline
select *
from parts p
where price >= (
select avg(price)
from parts pa
where pa.productline = p.productline)

MySql - How to get a sum of a particular column by joining three tables along with filters

There are three tables
Inventory - Which contains the stock information
Order - Which contains the store information of an order
OrderParts - Which contains the Parts associated with the order
Inventory Table
Order Table
Order Parts Table
Below Expected Report needs to be generated
Query Tried to achieve the above result
SELECT
inventory.partNumber, inventory.storeId, SUM(parts.quantity) as orderedQuantity,
inventory.availableQuantity
FROM
(SELECT *, SUM(availableQuantity) AS availQty
FROM
inventory AS inventory
GROUP BY storeId , partNumber) AS inventory
LEFT JOIN
(SELECT
*
FROM
order
GROUP BY storeId) AS order ON order.storeId = inventory.storeId
LEFT JOIN
(SELECT
*
FROM
orderParts) AS parts ON inventory.partNumber = parts.partNumbe
where inventory.partNumber in ("A1234", "B1234");
GROUP BY order.storeId , parts.partNumber
Getting null for Ordered Quantity
Kindly let me know the way to get the cumulative Ordered quantity as expected. Thanks in Advance.
A relatively simple method is union all and aggregation:
select storeid, partnumber,
sum(availableqty) as availableqty,
sum(orderedqty) as orderedqty
from (select storeid, partnumber, availableqty, 0 as orderedqty
from inventory
union all
select o.storeid, op.partnumber, 0, op.quantity
from orderparts op join
orders o
on op.ordernumber = o.ordernumber
) sp
group by storeid, partnumber;
Your question doesn't explicitly describe the filters, but you can add filters in either the subqueries or the outer query.

unable to group the field with same item_hsn and sum the quantity of it using group by sql statements

Select purchase_items.item_hsn, sales_items.item_hsn, purchase_items.quantity as qty1,
sales_items.quantity as 'qty2',
purchase_items.quantity-sales_items.quantity as 'Difference'
from purchase_items
LEFT JOIN sales_items ON purchase_items.item_hsn = sales_items.item_hsn;
Here this is my query i have two tables purchase_items and sales_items i want to generate the stock of items with respect to item_hsn and its quantity
stock=purchase-sales;
Unable to do so i am a newbie out here please help me out with this:
I have added the output its getting confused with two same item_hsn with different quantities.
You seem to want aggregation:
select
i.item_hsn,
sum(i.quantity) as qty1,
coalesce(sum(s.quantity), 0) as qty2,
sum(i.quantity) - coalesce(sum(s.quantity), 0) - s.quantity as diff
from purchase_items i
left join sales_items s on p.item_hsn = s.item_hsn
group by i.item_hsn
Notes:
coalesce() ensures that we get proper results for items that have no sales
Don't use single quotes for identifiers; they should be used for literal strings only. Instead, use backticks, or better yet use unquoted identifiers.
I suspect that your underlying tables have multiple rows per item hsn. This suggests a different approach for the aggregation. I would use union all to restructure the data and then aggregate:
select item_hsn, sum(purchases) as purchases, sum(sales) as sales,
sum(purchases) - sum(sales) as difference
from ((select pi.ite_hsn, pi.quantity as purchases, 0 as sales
from purchase_items pi
) union all
(select si.ite_hsn, 0 as purchases, si.quantity as sales
from sales_items si
)
) ps
group by item_hsn
I'm not sure where the item name is coming from. It is not being returned by the query you have written. But you should be able to tweak this query to include it.
"Select purchase_items.item_hsn, purchase_items.item_name, sales_items.item_hsn, (SELECT sum(quantity) FROM purchase_items
WHERE purchase_items.item_hsn=sales_items.item_hsn) as 'qty2', (SELECT sum(quantity) FROM sales_items WHERE purchase_items.item_hsn=sales_items.item_hsn)
as 'qty1' ,(SELECT sum(quantity) FROM purchase_items WHERE purchase_items.item_hsn=sales_items.item_hsn) - (SELECT sum(quantity) FROM sales_items WHERE
purchase_items.item_hsn=sales_items.item_hsn) as 'Difference' from purchase_items,sales_items WHERE purchase_items.item_hsn = sales_items.item_hsn
GROUP BY purchase_items.item_hsn, sales_items.item_hsn"
**here is the query for stock**

MySQL Join with sum()

I have two tables; One contains for products stats and another one contains additional stats
StatsHourly:
id
product_id (can be multiple)
amount
cost
time
StatsValues:
id
product_id (can be multiple)
value (double)
I need to join those two tables and get something like this in the result:
product_id
sum (amount)
sum (cost)
sum (value)
I'm trying to do this:
"SELECT
SUM(s.amount) as amount,
SUM(s.cost) as cost
FROM StatsHourly s
LEFT JOIN (
SELECT
COALESCE(SUM(value), 0) as value
FROM StatsValues
GROUP BY product_id
) value v ON v.product_id = s.product_id
WHERE 1
AND s.product_id = :product_id";
This doesn't work. Could someone show me the right way to do it?
You have an extra comma after as cost:
SUM(s.cost) as cost, <-- here
You also use 2 aliases for the subquery, you should remove value from there:
) value v
You do not use any output from the subquery.
Coalesce() is unnecessary in the subquery.
This works (tested):
SELECT
s.product_id as product_id,
s.amount_s as amount,
s.cost_s as cost,
v.value_v as value
FROM
(SELECT
product_id,
SUM(amount) as amount_s,
SUM(cost) as cost_s
FROM StatsHourly
GROUP BY product_id) as s
LEFT JOIN
(SELECT
product_id,
SUM(value) as value_v
FROM StatsValues
GROUP BY product_id) as v
ON v.product_id = s.product_id;
WHERE s.product_id = 'product_id';
The point is:
As you have multiple equal product_id in BOTH table you have to make two aggregated tables through subqueries that makes the product_id unique and sum all appropriate rows.
After that you can join and you select the already aggregated values.
Regards

Calculate Sum() but excluding JOIN

In the sales table, there is a point field. I want to sum(point) when grouping by sales.submit_date but that wont add up correctly because it will duplicate the records from JOIN
SELECT
COUNT(DISTINCT sales.sales_id) as TotalSales,
COUNT(DISTINCT sales_lines.id) as TotalLiness
FROM `sales`
JOIN sales_lines ON sales_lines.sales_id = sales.sales_id
GROUP BY sales.submit_date
SQL above, this will count the number of sales in the sales table and also count number of lines in the sales_lines (number of lines matched to sales_lines.sales_id = sales.sales_id). This seem to work fine.
How do I sum(`sales.point') in the sales only?
You could aggregate sales_lines up to the sales grain.
SELECT
S.submit.date,
,sum(s.point)
,COUNT(s.sales_id) as TotalSales
,SUM(SL.SalesLines) as TotalLines
FROM
sales S
INNER JOIN
(Select
sales_id
,count(distinct id) as SalesLines
FROM
sales_lines
GROUP BY
sales_id) SL
ON S.sales_id = SL.sales_id3
GROUP BY
s.submit_date