MySQL - Finding out Balancing Figure From 2 Tables - sql

I have 2 tables like this:
Stock Table
product_id bigint(20)
qty float
Sales Table
product_id bigint(20)
qty float
Sample Data
Stock Table
product_id---qty
1---10
2---11
3---20
4---50
1---10
3---10
Sales Table
product_id---qty
1---2
2---5
3---20
4---40
1---7
I want the following Output after running the Query
product_id---qty
1---11
2---6
3---10
4---10
Well, as spender ask I am trying to more clear the situation.
First of All, let's think that I store
10 quantity of product 1
11 quantity of product 2
20 quantity of product 3
50 quantity of product 4
10 quantity of product 1 (now I have total 20 of product 1)
10 quantity of product 3 (now I have total 30 of product 3)
Secondly, let's think that I sell
2 quantity of product 1
5 quantity of product 2
20 quantity of product 3
40 quantity of product 4
7 quantity of product 1 (now I have sold total 9 of product 1)
Thirdly, I want to know how much stock is now in my hand
11 quantity of product 1 (20-9 = 11)
6 quantity of product 2 (11-5 = 6)
10 quantity of product 3 (30-20 = 10)
10 quantity of product 4 (50-4 = 10)
My Question is: To find out this stock what is the Query?
Thanks in Advance for answering my question.

This answer works in Oracle - don't have MySql so can't test there
select product_id, sum(qty) from
(
select product_id, qty from stock
union all
select product_id, (-1 * qty) from sales
) as a
group by prod

You question is lacking detail and looks like it might even contain typos in the presented data. I'm going to make the assumption you are trying to calculate the diff between stock quantities and sales quantities, despite your data not actually supporting this (!!!). It looks like you require the following:
select
st.product_id,
sto.qty-st.qty
from
salesTable as st
join stockTable as sto on sto.product_id=st.product_id

Chris's answer is absolutely correct. But for the information I want to add this one which I found on NET.
SELECT tunion.product_id, (
(IFNULL((SELECT SUM(s.qty) FROM stock s WHERE s.product_id=tunion.product_id),0))-
(IFNULL((SELECT SUM(p.qty) FROM sales p WHERE p.product_id=tunion.product_id),0)))
AS quantity
FROM (SELECT DISTINCT s.product_id FROM stock s
UNION ALL SELECT DISTINCT p.product_id FROM sales p)
AS tunion GROUP BY tunion.product_id

Related

SQL - Adding values from same column of different IDs

I have 2 tables product and inventory as shown below.
Product:
Product_ID Product_Description Price
100 Computer 30
200 Laptop 50
300 Printer 10
Inventory:
Product_ID Stock
100 40
200 15
300 50
From these both tables, I need a query to list Product ID, Product Description and quantity which has the maximum number of stock and add the stock of laptop to the display.
Expected Output:
Product_ID Product_Description Stock
300 Printer 65
The 65 is the result of 50 for printer & 15 for laptop.
Could you please help with a query for this at the earliest?
You can do it with MAX() aggregate function:
SELECT p.Product_ID, p.Product_Description,
MAX(CASE WHEN p.Product_Description = 'Laptop' THEN i.Stock END) +
MAX(i.Stock) Stock
FROM Product p INNER JOIN Inventory i
ON i.Product_ID = p.Product_ID
This code relies in SQLite's feature to return the row that contains the max value (in this case the last defined max).
See the demo.
Results:
Product_ID
Product_Description
Stock
300
Printer
65
You can use window functions. This uses a trick to whittle the data down to two rows, add up the stock using window functions and then chooses only one row for the non-laptop row (if any).
select p.*, sum(stock) over ()
from (select s.*, row_number() over (order by stock desc) as seqnum
from stock s
) s join
product p
on p.product_id = s.product_id
where s.seqnum = 1 or p.product_description = 'Laptop'
order by s.seqnum
limit 1;

Subtract aggregate of only certain rows from only other certain rows in the same table?

product saletype qty
-----------------------------
product1 regular 10
product1 sale 1
product1 feature 2
I have a sales table as seen above, and products can be sold 1 of 3 different ways (regular price, sale price, or feature price).
All sales regardless of type accumulate into regular, but sale and feature also accumulate into their own "saletype" also. So in the above example, I've sold 10 products total (7 regular, 1 sale, 2 feature).
I want to return the regular quantity minus the other two columns as efficiently as possible, and also the other saletypes too. Here is how I am currently doing it:
create table query_test
(product varchar(20), saletype varchar(20), qty int);
insert into query_test values
('product1','regular',10),
('product1','sale',1),
('product1','feature',2)
select
qt.product,
qt.saletype,
CASE WHEN qt.saletype = 'regular' THEN sum(qt.qty)-sum(lj.qty) ELSE sum(qt.qty) END as [qty]
from
query_test qt
left join
(
select product, sum(qty) as [qty]
from query_test
where saletype in ('sale','feature')
group by product
) lj on lj.product=qt.product
group by
qt.product, qt.saletype;
...which yields what I am after:
product saletype qty
-----------------------------
product1 feature 2
product1 regular 7
product1 sale 1
But I feel like there has to be a better way than essentially querying the same information twice.
You can use the window function sum and some arithmetic to do this.
select product,
saletype,
case when saletype='regular' then 2*qty-sum(qty) over(partition by product)
else qty end as qty
from query_test
This assumes there is atmost one row for saletype 'regular'.

Trying to count # distinct values of a field based on value of a different field

Looking for some help with my SQL query. I am trying to find a way to specify cases in which a customer purchases or sells at two different stores, but if they purchase at one store and sell at another, I don't care or want that to count.
I have tried this -
Select count(distinct store) OVER(Partition BY Customer)
but it doesn't like the distinct and causes an error. When I dont specify distinct, it will give me the count of all observations of that customer, instead of just the count of # of stores that they purchased from, or sold to.
Based on the data below, customer D is the type im looking to filter for.
My Raw Data:
Customer Type Qty Store
A Purchase 1 2
A Purchase 2 2
A Sale 3 1
B Sale 24 1
B Sale 12 1
C Purchase 4 2
D Sale 12 2
D Purchase 4 2
D Purchase 2 1
D Purchase 2 1
Any ideas?
select customer
from your_table
group by customer, type
having count(distinct store) > 1
Don't you just want to GROUP?
Select Count(store) FROM Blah GROUP BY Customer, Store
Edit: Ah I see what you want - you want a count of store over customer, sorry misread it!

Getting products from SQL query

I'm currently working on a proprietary shopping cart system and was having a few problems with getting products out with the correct pricing.
Basically my table structure is as follows:
Products table: (Only relevant columns are represented)
----------------------------------------------------
productid | product | descr | disporder| list_price|
----------------------------------------------------
1 name desc 1 0.00
2 name desc 4 0.00
3 name desc 2 2.45
Pricing table:
----------------------------------------
priceid | productid | price | variantid|
----------------------------------------
1 1 13.91 1
2 2 54.25 4
3 2 47.23 2
Variants Table:
-------------------------------
variantid | productid | active|
-------------------------------
1 1 Y
2 2 Y
3 2 Y
So, each product can have - and in most cases does have - multiple variants. My current SQL query I have managed to create thus far is:
SELECT
products.productid, product, descr, p.price, i.image_path
FROM
products
LEFT JOIN
pricing AS p
ON
p.variantid = (SELECT variantid FROM variants
WHERE productid = products.productid LIMIT 1)
LEFT JOIN
images_T AS i
ON
i.id = products.productid
GROUP BY
products.productid
ORDER BY
products.disporder
However, my problem arises when a product does not have a variant. If a product does not have a variant associated with it, the price will be in the list_price column of the products table. How would I go about performing a check to see if a product does indeed have a variant. If not, it should effectively bypass the variants table and get the pricing from list_price within the products table.
Yes, CASE is an option, or COALESCE:
SELECT
products.productid, product, descr,
COALESCE(products.list_price, p.price) AS price,
i.image_path
...
Just join both prices and when the first is NULL the other will be selected.
The simplest way is to use a CASE in the SELECT clause, like so:
SELECT
products.productid, product, descr,
CASE
WHEN p.price IS NULL
THEN products.list_price
ELSE p.price
END AS price,
i.image_path
[...]
Since you're left-joining on pricing/variants, p.price should reliably be NULL for products with no variants.
Hopefully that's what you meant by "bypassing" the variants table. :)
You can do a full join with variants table (which will ONLY give you producs which have variants), and then UNION it with a join of producs and pricing where there exists no varian (using AND NOT EXISTS (SELECT 1 from variants WHERE p.productid=v.productid and p.variantid =v.variantid)
Otherwise, use CASE on pricing.price

Using SQL to find the total number of customers with over X orders

I've been roasting my brain with my limited SQL knowledge while attempting to come up with a query to run a statistic on my orders database.
Table ORDERS is laid out like this:
CustomerID ProductID (etc)
1 10
1 10
1 11
2 10
4 9
Each purchase is recorded with the customer id and the product ID - there CAN be multiple records for the same customer, and even multiple records with the same customer and product.
I need to come up with a query that can return the amount of customers who bought between X and X distinct products - for example, 3 customers bought less then 5 different products, 10 bought from 5-10 different products, 1 bought over 10 different products.
I'm pretty sure this has something to do with derived tables, but advanced SQL is a new fairly craft to me. Any help would be appreciated!
Try this:
SELECT T1.products_bought, COUNT(T2.cnt) AS total
FROM (
SELECT '<5' AS products_bought, 0 AS a, 4 AS b
UNION ALL
SELECT '5-10', 5, 10
UNION ALL
SELECT '>10', 11, 999999
) T1
LEFT JOIN
(
SELECT COUNT(DISTINCT ProductID) AS cnt
FROM ORDERS
GROUP BY CustomerID
) T2
ON T2.cnt BETWEEN T1.a AND T1.b
GROUP BY a, b
Result:
products_bought total
<5 3
5-10 0
>10 0