Calculate amount between two MySQL tables - php

I have two tables one for incoming goods and inventory and another for the exit of products.
How do I do a select in mysql to return the amount available in stock without using PHP.
In the case would STOCK - OUTPUTS.
Thanks!

I think you want something like this:
SELECT
(SELECT SUM(quantity) FROM stock) -
(SELECT SUM(quantity) FROM outputs) AS 'slo'

Related

Laravel, How to make SQL request to few independent tables in a request

I'm trying to build a filter by price in e-store.
I need to get necessary products and min/max value of a price column.
A native request would looks like:
SELECT *
FROM product p, (
SELECT
MIN(price) AS min_price,
MAX(price) AS max_price
FROM product
LIMIT 1
) extreme_values
WHERE
# some condition
But I cannot figure out, how to do it by Doctrine.
Google suggests the JOIN stuffs only.
Please, advise, is there any way to make a request to few tables by Doctrine in a once with no JOIN

MySQL question: The right way to calculate some data from different tables

We have a table A in which we store data about user investments; example columns user_id, project_id, amount.
We also have a table B in which we store data about projects and the total amount of investments; columns project_id and total_amount.
With PHP we can count the amount from A and write total_amount to B.
The question: Is it possible at the MYSQL level to automatically calculate data in order to avoid unnecessary operations in PHP?
If Yes, could you show me an example?
UPDATE tableB
LEFT JOIN (
SELECT project_id, SUM(amount) total_amount
FROM tableA
GROUP BY project_id
) amounts
ON amounts.project_id = tableB.project_id
SET tableB.code_counter=amounts.total_amount
This should work.
You can use following query to calculate total amount:
"SELECT SUM(amount) as total_amount from table_a group by project_id"

MySQL & PHP: Selecting buyer records by product purchased

I have a somewhat complex MySQL query I'm attempting to derive but I'm just confusing the hell out of myself.
I have several tables: products, stores, buyer, payment and buyer_purchase.
buyer_purchase is basically made up of foreign keys. This table more or less links all the other together. The tables are filled up with junk data. The actual records themselves are not as important as the methods used to retrieve them.
I need to be able to select buyers who have purchased a specific product, how many of that item they've purchased, what store they bought it from, and the payment method used.
It will all be displayed in a webpage using PHP in the following manner:
Product1
name of buyer1
Payment method
Number Purchased
Store purchased From
product2
Name of buyer1
Payment
Number Purchased
Store Purchased from
Name of buyer2
Payment
etc.
I have a query that somewhat works:
SELECT products.item, stores.seller_name, buyer.f_name, buyer.l_name, payment.company
FROM buyer_purchases
INNER JOIN products
ON products.id = buyer_purchases.product_listings_id
INNER JOIN payment
ON payment.id = buyer_purchases.buyer_id
INNER JOIN buyer
ON buyer.id = buyer_purchases.buyer_id
INNER JOIN stores
ON stores.id = buyer_purchases.product_listings_stores_id
ORDER BY products.item
This will return all the data I need in a joined table, but getting it formatted to display as I need is what is confusing me. Obviously, I need to invoke a COUNT to display how many of a given product someone bought, but I'm not sure how to implement it. Further, I think I need GROUP BY rather than ORDER BY, but GROUP BY eliminates all but one record for each product. I've not been able to implement a subquery that MySQL doesn't complain about.
Right now, I'm trying to pull all of the data from the tables in a single query, and store it as a PHP array I can iterate through. If this is not the best way to go about this process, I can find another way.
I guess you just need more experience with MySQL, the trick is in the way you group the elements. In this case you want to group by multiple fields.
SELECT
products.item as product,
concat(buyer.f_name,' ',buyer.l_name) as buyer,
payment.company as payment,
count(products.id) as number_purchased
stores.seller_name as store,
FROM buyer_purchases
INNER JOIN products
ON products.id = buyer_purchases.product_listings_id
INNER JOIN payment
ON payment.id = buyer_purchases.buyer_id
INNER JOIN buyer
ON buyer.id = buyer_purchases.buyer_id
INNER JOIN stores
ON stores.id = buyer_purchases.product_listings_stores_id
GROUP BY buyer.id,stores.id,payment.id
ORDER BY products.item
You can have multiple ORDER BY clauses which work in order, so looks like you want ORDER BY products.item, buyer.id which will list all records for item 1 first, ordered by customer, then all records for item 2 ordered by cutomer etc

Most efficient way of getting first payment method used by all users

Lets say I have a table in a MSSQL database called "Customers". I also have a table called "Orders", each of which contains a "CustomerID". What I want to do, is to generate a summary of what payment method (let's call that "PaymentMethod") was used for the first "Order" of every "Customer".
The method I have been using for this is to conduct my customer selection query...
SELECT <Columns> FROM Customers <WHERE>
...and then for each result, conduct a separate query to obtain the customer's first order's payment method:
SELECT TOP 1 PaymentMethod FROM Orders ORDER BY Timestamp ASC
This process has the benefit of obtaining the data I want in a very simple way that's easy to modify, but the huge disadvantage of meaning a query is carried out for every customer, which could mean tens-of-thousands of extra queries every single time!
Is there a more efficient way of doing this that I'm not thinking of? I'm racking my brain to think of a way of selecting directly from the "Orders" table to begin with, but the requirement for the query to not only group by "CustomerID" but also fetch the MIN() of "Timestamp" and then return "PaymentMethod" of the MIN() record doesn't seem to work?
You can use ROW_NUMBER for this:
SELECT PaymentMethod
FROM (
SELECT PaymentMethod,
ROW_NUMBER() OVER (PARTITION BY CustomerID
ORDER BY Timestamp ASC) AS rn
FROM Orders ) AS t
WHERE t.rn = 1
The above query picks the earliest-per-group record.
I guess this helps you.
SELECT C.* , O.PAYMENTMETHOD FROM Customers C
INNER JOIN Orders O ON O.CustomerID = C.CustomerID
WHERE O.OrderTime =
(SELECT TOP 1 OrderTime FROM Customers WHERE CustomerID = C.CustomerID) -- selects customer first order based on min time

Returning rows based on sum of column

I'm trying to retrieve a subset of data based on the sum of a column. The goal is a script to release backordered items. Say we have 100 BO products and get 50 in stock. I'd like to update the oldest orders where the sum of order qty < 50. So something like:
Sample Schema:
Orders Table:
order_id, order_date
order_products Table:
order_product_id, order_id, product_id, product_status, ordered_quantity
select * from products
where products_id=1234
and status=1
and sum(products_qty) < 50;
Where sum(products_qty) is the total returned qty, not just for the individual row. Not sure if this is possible with a single query or even a subquery, but thought I would ask the experts here first. I'm trying to avoid returning all the rows and then manually count up till I reach the limit.
You need use GROUP by and Having
select * from products
where products_id=1234
and status=1
group by YourGroupingFields
Having sum(products_qty) < 50;
based on your info:
select product_id from products
where status=1
group by product_id
Having sum(products_qty) < 50;
will be return product_id for which total quantity less 50
When you're using aggregate functions like SUM() and COUNT(), you can't use them in WHERE clauses. WHERE clauses are applied row-by-row as the database scans the table/indexes, which means that the results of the aggregate functions aren't available yet.
Filtering by aggregate results has to be done using HAVING, which is essentially done as the last step before returning data to the client.
From the sounds of your requirement, you need a running count to be kept, until you've retrieved enough rows/orders to use up the new product being entered. This can't be done with a single query. You'd need to use a server-side variable to keep track of how much product's been "used up" by the individual backorders.
Going off the top of my head, something like this might do the trick:
SET #Available = 50;
SELECT order_id, SUM(ordered_quantity), #Available := #Available - SUM(ordered_quantity) AS available
FROM order_products
WHERE product_id = XXX
GROUP BY order_id, product_id
HAVING available >= 0;
with whatever extra WHERE clauses so you get the oldest backorders first

Categories