Updating a column after deleting a row - mysql

I'm learning to use MySQL and therefore I'm trying to make a simple inventory management.
If I delete an invoice how can I not just delete from the invoice table and from the invoiceItemTable as well but update the "Amount" column with the subtraction value at the right store in my Inventory Table? Since if I want to do
SUM(inventory.amount) - SUM(SELECT amount FROM InvoiceItemTable WHERE invoice_id = 1
GROUP BY Product_id)
this will fail because subqueries have more than 1 rows. Below you can see my database structure.
InvoceTable
+---+----------------+----------+
|ID | invoice_number | Store_id |
+---+----------------+----------+
| 1 | 1234 | 1 |
+---+----------------+----------+
InvoiceItemTable
+---+----------------+------------+---------+
|ID | invoice_id | Product_id | Amount |
+---+----------------+------------+---------+
| 1 | 1 | 1 | 5 |
+---+----------------+------------+---------+
| 2 | 1 | 1 | 5 |
+---+----------------+------------+---------+
| 3 | 2 | 1 | 10 |
+---+----------------+------------+---------+
Inventory
+---+----------------+---------+----------+
|ID | Product_id | Amount | Store_id |
+---+----------------+---------+----------+
| 1 | 1 | 15 | 1 |
+---+----------------+---------+----------+
| 2 | 2 | 15 | 1 |
+---+----------------+---------+----------+
| 3 | 2 | 15 | 2 |
+---+----------------+---------+----------+
UPDATE:
Expectation after the queries:
InvoceTable
+---+----------------+----------+
|ID | invoice_number | Store_id |
+---+----------------+----------+
| | | |
+---+----------------+----------+
InvoiceItemTable
+---+----------------+------------+---------+
|ID | invoice_id | Product_id | Amount |
+---+----------------+------------+---------+
| 3 | 2 | 1 | 10 |
+---+----------------+------------+---------+
Inventory
+---+----------------+---------+----------+
|ID | Product_id | Amount | Store_id |
+---+----------------+---------+----------+
| 1 | 1 | 5 | 1 |
+---+----------------+---------+----------+
| 2 | 2 | 5 | 1 |
+---+----------------+---------+----------+
| 3 | 2 | 15 | 2 |
+---+----------------+---------+----------+

you'd need to use sum inside the subquery:
select SUM(inventory.amount) - (SELECT SUM(amount) FROM InvoiceItemTable WHERE invoice_id = 1 GROUP BY Product_id)
from inventory
check sqlfiddle for your database scheme and the running query.
this query should decrease the Inventory table's amount column according to invoiceitemtable table:
update Inventory set Amount = Amount - (SELECT SUM(amount) FROM InvoiceItemTable WHERE invoice_id = 1 AND Product_id = Inventory.Product_id GROUP BY Product_id)

SUM(inventory.amount) - (SELECT SUM(amount) FROM InvoiceItemTable WHERE invoice_id = 1 GROUP BY Product_id)

Related

How can I get a purchase check in MySQL

I am not able to figure out how I can get the following result with one MySQL Query:
I have two tables:
shop_items
| id | description | price | active |
+----+-------------+-------+--------+
| 1 | product_1 | 5 | 1 |
+----+-------------+-------+--------+
| 2 | product_2 | 10 | 1 |
+----+-------------+-------+--------+
| 3 | product_3 | 15 | 0 |
+----+-------------+-------+--------+
inventory_items (the shop_items a user purchased)
| id | item_id | user_id | active |
+----+---------+---------+--------+
| 1 | 2 | 1 | 1 |
+----+---------+---------+--------+
| 2 | 1 | 1 | 0 |
+----+---------+---------+--------+
I want to see all shop_items where active = 1 including a row called purchased = 0 or 1 based on inventory_items -> matching user_id (where user_id = something) and active = 1
Example output based on the data from above tables -> where user_id = 1:
| item_id | price | description | purchased |
+---------+-------+-------------+-----------+
| 1 | 5 | product_1 | 0 |
+---------+-------+-------------+-----------+
| 2 | 10 | product_2 | 1 |
+---------+-------+-------------+-----------+
What query do I need for this output?
Please note: I only need the result from ONE user_id which I can change within the query :)
Test
SELECT shop_items.*, COALESCE(inventory_items.active, 0) purchased
FROM shop_items
LEFT JOIN inventory_items ON shop_items.id = inventory_items.item_id
AND user_id = 1
WHERE shop_items.active = 1

How to select only first matching value from another table in MySQL?

Here is my database schema:
Payment table:
+------------+--------+--------+---------------------+
| payment_id | tab_id | amount | created |
+------------+--------+--------+---------------------+
| 1 | 1 | 5 | 2017-05-22 12:14:27 |
| 2 | 2 | 10 | 2017-05-22 12:15:21 |
| 3 | 2 | 1 | 2017-05-22 13:11:14 |
+------------+--------+--------+---------------------+
Tab table:
+------------+----------------+
| tab_id | service_charge |
+------------+----------------+
| 1 | 1 |
| 2 | 3 |
+------------+----------------+
I need to calculate total amounts (amount + service_charge) per payment, but service_charge should be included only in first payment matching tab_id.
My current query:
SELECT
payment.payment_id,
(payment.amount + tab.service_charge) as total_amount,
payment.created
FROM payment
INNER JOIN tab
ON payment.tab_id = tab.tab_id;
Actual result:
As you can see below service_charge from tab_id = 2 included twice (payment_id = 2 and payment_id = 3).
+------------+-----------------+---------------------+
| payment_id | total_amount | created |
+------------+-----------------+---------------------+
| 1 | 6 | 2017-05-22 12:14:27 |
| 2 | 13 | 2017-05-22 12:15:21 |
| 3 | 4 | 2017-05-22 13:11:14 |
+------------+-----------------+---------------------+
Expected result:
total_amount should not include service_charge in payment_id = 3 as shown below.
+------------+-----------------+---------------------+
| payment_id | total_amount | created |
+------------+-----------------+---------------------+
| 1 | 6 | 2017-05-22 12:14:27 |
| 2 | 13 | 2017-05-22 12:15:21 |
| 3 | 1 | 2017-05-22 13:11:14 |
+------------+-----------------+---------------------+
You should determine which is the first payment matching the tab_id and then based on that info, decide if you want to use the service_charge or not:
SELECT
payment.payment_id,
payment.amount + if (payment.created=m.mintime, tab.service_charge, 0) as total_amount,
payment.created
FROM payment
INNER JOIN tab
ON payment.tab_id = tab.tab_id
JOIN (
SELECT tab_id, min(created) as 'mintime'
FROM payment
GROUP BY tab_id
) AS m on m.tab_id = payment.tab_id;

Get as much as possible rows until a given minimum amount is achieved in MySQL

For example we have the following Query:
SELECT
item_id,
order_id,
product_id,
qty
FROM
orders
WHERE
product_id = 18253
ORDER BY
item_id ASC;
... and that's the result of it:
+---------+----------+------------+------+
| item_id | order_id | product_id | qty |
+---------+----------+------------+------+
| 15329 | 7369 | 18253 | 3 |
| 15330 | 7370 | 18253 | 1 |
| 15331 | 7371 | 18253 | 7 |
| 15332 | 7372 | 18253 | 1 |
| 15333 | 7373 | 18253 | 1 |
| 15334 | 7377 | 18253 | 1 |
| 15336 | 7379 | 18253 | 2 |
| 15337 | 7380 | 18253 | 1 |
| 15340 | 7383 | 18253 | 1 |
| 15341 | 7384 | 18253 | 1 |
+---------+----------+------------+------+
10 rows in set (0,04 sec)
Now I want to get all possible rows (as much as possible) until the sum of qty is at least five. Five should be the minimum quantity. Sorted by ascending (item_id).
+---------+----------+------------+------+
| item_id | order_id | product_id | qty |
+---------+----------+------------+------+
| 15329 | 7369 | 18253 | 3 | // 3
| 15330 | 7370 | 18253 | 1 | // 4
| 15331 | 7371 | 18253 | 7 | // 11
+---------+----------+------------+------+
So the sum of qty above is 3, 4, 11. The third row makes the sum 5 or above so that's all I need.
Another example when I have a quantity of 13 in my inventory:
+---------+----------+------------+------+
| item_id | order_id | product_id | qty |
+---------+----------+------------+------+
| 15329 | 7369 | 18253 | 3 | // 3
| 15330 | 7370 | 18253 | 1 | // 4
| 15331 | 7371 | 18253 | 7 | // 11
| 15332 | 7372 | 18253 | 1 | // 12
| 15333 | 7373 | 18253 | 1 | // 13
+---------+----------+------------+------+
How can I do that, is there a possibility?
thanks :)
You can generate cummulative sum of quantity in the order of increasing item_id and then filter out the result as needed:
select *
from (
select item_id,
order_id,
product_id,
qty,
#cum_qty := #cum_qty + qty as cum_qty
from orders, (select #cum_qty := 0) t
where product_id = 18253
order by item_id
) t
where cum_qty - qty < 5; -- or 13 or whatever
Demo
Unless I'm missing something, this can be done by adding the limit clause to your query, like:
SELECT
item_id,
order_id,
product_id,
qty
FROM
orders
WHERE
product_id = 18253
ORDER BY
item_id ASC;
LIMIT 5;

MySQL SUM and GROUP BY from AS column

table1 structure and sample data
+----+-------------+----------+------+-------+
| ID | DESCRIPTION | QUANTITY | EACH | PRICE |
+----+-------------+----------+------+-------+
| 1 | Product 1 | 1 | 12 | 1*12 |
| 2 | Product 2 | 2 | 3 | 2* 3 |
| 3 | Prodcut 3 | NULL | 3 | |
| 4 | Product 1 | 2 | 10 | 2*10 |
| 5 | Product 3 | NULL | 7 | |
+----+-------------+----------+------+-------+
MySQL query:
SELECT
DESCRIPTION,
QUANTITY,
EACH,
COALESCE(QUANTITY, 1) * EACH AS PRICE
FROM table1
GROUP BY DESCRIPTION
How could I make SUM for the PRICE column and GROUP BY the DESCRIPTION column? I don't want to use UPDATE because I can't change the values in the table1.
Well why can't you add SUM(COALESCE(QUANTITY, 1) * EACH) AS PRICETOTAL in your select list.
SELECT
DESCRIPTION,
SUM(COALESCE(QUANTITY,1)*each) as 'Price'
FROM table1
GROUP BY DESCRIPTION
returns
DESCRIPTION Price
Product 1 32
Product 2 6
Product 3 10

Combine multiple select statement in one result table

I have two tables, one for sales and another for stock.
I want to select location id, item id, size id and sales qty from sales table, while I want just to select stock qty from stock table for the same location id and size id from sales table, like this:
Sales table:
------------------------------------
| loc_id | item_id | size_id | qty |
------------------------------------
| 5 | 11321 | 1 | 5 |
| 5 | 11321 | 2 | 8 |
| 5 | 11321 | 3 | 4 |
| 5 | 11321 | 2 | 1 |
Stock table:
------------------------------------
| loc_id | item_id | size_id | qty |
------------------------------------
| 5 | 11321 | 1 | 3 |
| 5 | 11321 | 2 | 7 |
| 5 | 11321 | 3 | 9 |
So the result after select should be like this:
------------------------------------------------------
| loc_id | item_id | size_id | sales_qty | stock_qty |
------------------------------------------------------
| 5 | 11321 | 1 | 5 | 3 |
| 5 | 11321 | 2 | 9 | 7 |
| 5 | 11321 | 3 | 4 | 9 |
Here's what I tried to do:
SELECT SUM(T1.qty) AS `salesQty`, SUM(T2.qty) AS `stockQty`, T1.size_id,
T1.loc_id
FROM sales T1
INNER JOIN stock T2 ON T2.item_id = T1.item_id AND T2.size_id = T1.size_id
WHERE T1.item_id = '11321'
AND T1.size_id IN (1,2,3)
AND T1.loc_id IN (5)
GROUP BY T1.size_id, T1.loc_id
But stock qty always wrong!
select
q1.loc_id
,q1.item_id
,q1.size_id
,sum(case when q1.Type='Sales' then q1.Qty else 0 end) as sales_qty
,sum(case when q1.Type='Stock' then q1.Qty else 0 end) as stock_qty
from (
select
T1.loc_id
,T1.item_id
,T1.size_id
,'Sales' as Type
,SUM(T1.qty) AS Qty
from sales T1
group by
T1.loc_id
,T1.item_id
,T1.size_id
union all
select
T2.loc_id
,T2.item_id
,T2.size_id
,'Stock' as Type
,SUM(T2.qty) AS Qty
from stock T2
group by
T2.loc_id
,T2.item_id
,T2.size_id) q1
group by
q1.loc_id
,q1.item_id
,q1.size_id