Compare two tables to get the differences between them - mysql

Hello I have two tables:
Table: 1 11_counted_stock
id_counted_stock part_number Number of Tag quantity
1 abcde 2 1000
2 aaaaa 4 222
3 eeeee 6 442
Table:2 11_stock_actual_whs_costed
id_stock material batch A.stock
1 abcde 12334 500
2 aaaaa 23543 233
3 xxxxx 234234 299
Result Query Im looking for
Material Stock Counted_Stock Difference
abcde 500 1000 -500
aaaaa 233 222 11
eeeee 0 442 -442
xxxxx 299 0 299
Thanks a lot!
This is my best attempt but I could only sum :(
SELECT mat, qty, SUM(qty) as TotalQty
FROM (
SELECT 11_counted_stock.part_number AS mat, (11_counted_stock.quantity) AS qty
FROM 11_counted_stock
GROUP BY 11_counted_stock.part_number
UNION
SELECT 11_stock_actual_whs_costed.material, SUM(11_stock_actual_whs_costed.available_stock) AS quantity
FROM 11_stock_actual_whs_costed
GROUP BY 11_stock_actual_whs_costed.material
) as t
GROUP BY mat
;

SELECT Material,
SUM(Stock) AS Stock,
SUM(Counted_Stock) AS Counted_Stock,
SUM(Stock - Counted_Stock) AS Difference
FROM (
SELECT part_number AS Material, 0 AS Stock, quantity AS Counted_Stock
FROM 11_counted_stock
UNION ALL
SELECT material, stock, 0
FROM 11_stock_actual_whs_costed
) total
GROUP BY Material;

Related

How can I display top 3 products with its price and arrange by average prices?

I have this records in products table with product_id and its price
product_id
price
1
150
1
190
2
20
2
12
3
123
4
513
5
157
5
147
and I want to get the top 3 products and arrange it by average price something like this
product_id
price
avg_price
4
513
513
1
150
170
1
190
170
5
157
152
5
147
152
how to write/code it in sql query or laravel eloquent query?
WITH AverageCTE AS
(
SELECT product_id, AVG(avg_price) as avg_price
FROM products
GROUP BY product_id
)
SELECT p.product_id, price, avg_price
FROM product p JOIN
(SELECT * FROM AverageCTE ORDER BY avg_price DESC LIMIT 3) a
on p.product_id = a.product_id
ORDER BY avg_price DESC

count and sum function not working in left join

I have the following 3 tables and i would like to know the correct sql for the expected result as below.
my sql here is not working;
select h.pid,
h.name,
sum(r.amount1) as total1,
sum(r.amount2) as total2,
count(g.pid) as times,
sum(g.take) as totaltaken
from history h
left join rpt_revenue r on h.pid=r.pid
left join guest g on g.pid=r.pid
group by h.pid, h.name;
history
pid name
1 peter
2 may
rpt_revenue
id pid amount1 amount2
1 1 10.00 11.00
2 2 20.00 20.00
3 1 2.00 2.00
4 2 2.00 2.00
guest
gid pid id take
1 1 1 2
2 1 3 2
3 2 2 3
expected result
pid total1 total2 times totaltaken
1 12.00 13.00 2 4
2 22.00 22.00 1 3
So to be able to use aggregate function over join, you should first aggregate your data in a join subquery and then aggregate all of them at the top level
here some examples of aggregation

Conditional Window Functions

I have a sales table that looks like this:
store_id cust_id txn_id txn_date amt industry
200 1 1 20180101 21.01 1000
200 2 2 20200102 20.01 1000
200 2 3 20200103 19 1000
200 3 4 20180103 19 1000
200 4 5 20200103 21.01 1000
300 2 6 20200104 1.39 2000
300 1 7 20200105 12.24 2000
300 1 8 20200105 25.02 2000
400 2 9 20180106 103.1 1000
400 2 10 20200107 21.3 1000
Here's the code to generate this sample table:
CREATE TABLE sales(
store_id INT,
cust_id INT,
txn_id INT,
txn_date bigint,
amt float,
industry INT);
INSERT INTO sales VALUES(200,1,1,20180101,21.01,1000);
INSERT INTO sales VALUES(200,2,2,20200102,20.01,1000);
INSERT INTO sales VALUES(200,2,3,20200103,19.00,1000);
INSERT INTO sales VALUES(200,3,4,20180103,19.00,1000);
INSERT INTO sales VALUES(200,4,5,20200103,21.01,1000);
INSERT INTO sales VALUES(300,2,6,20200104,1.39,2000);
INSERT INTO sales VALUES(300,1,7,20200105,12.24,2000);
INSERT INTO sales VALUES(300,1,8,20200105,25.02,2000);
INSERT INTO sales VALUES(400,2,9,20180106,103.1,1000);
INSERT INTO sales VALUES(400,2,10,20200107,21.3,1000);
What I would like to do is create a new table, results that answers the question: what percentage of my VIP customers have, since January 3rd 2020, shopped i) at my store only; ii) at my store and at other stores in the same industry; iii) at only other stores in the same industry? Define a VIP customer to be someone who has shopped at a given store at least once since 2019.
Here's the target output table:
store industry pct_my_store_only pct_both pct_other_stores_only
200 1000 0.5 0.5 0.0
300 2000 0.5 0.5 0.0
400 1000 0.0 1.0 0.0
I'm trying to use window functions to accomplish this. Here's what I have so far:
CREATE TABLE results as
SELECT s.store_id, s.industry,
COUNT(DISTINCT (CASE WHEN s.txn_date>=20200103 THEN s.cust_id END)) * 1.0 / sum(count(DISTINCT (CASE WHEN s.txn_date>=20200103 THEN s.cust_id END))) OVER (PARTITION BY s.industry) AS pct_my_store_only
...AS pct_both
...AS pct_other_stores_only
FROM sales s
WHERE sales.txn_date>=20190101
GROUP BY s.store_id, s.industry;
The above does not seem to be correct; how can I correct this?
Join the distinct store_ids and industries to the concatenated distinct store_ids and industries for each customer and then use window function avg() with the function find_in_set() to determine if a customer how many customer have shopped or not from each store:
with
stores as (
select distinct store_id, industry
from sales
where txn_date >= 20190103
),
customers as (
select cust_id,
group_concat(distinct store_id) stores,
group_concat(distinct industry) industries
from sales
where txn_date >= 20190103
group by cust_id
),
cte as (
select *,
avg(concat(s.store_id) = concat(c.stores)) over (partition by s.store_id, s.industry) pct_my_store_only,
avg(find_in_set(s.store_id, c.stores) = 0) over (partition by s.industry) pct_other_stores_only
from stores s inner join customers c
on find_in_set(s.industry, c.industries) and find_in_set(s.store_id, c.stores)
)
select distinct store_id, industry,
pct_my_store_only,
1 - pct_my_store_only - pct_other_stores_only pct_both,
pct_other_stores_only
from cte
order by store_id, industry
See the demo.
Results:
> store_id | industry | pct_my_store_only | pct_both | pct_other_stores_only
> -------: | -------: | ----------------: | -------: | --------------------:
> 200 | 1000 | 0.5000 | 0.5000 | 0.0000
> 300 | 2000 | 0.5000 | 0.5000 | 0.0000
> 400 | 1000 | 0.0000 | 1.0000 | 0.0000

How to use group_concat with the sum of quantity based on price?

This is my table which store id with its qty and price. I would like to sum qty based on price. Sometimes the qty might be show 0 if qty is negative value. Thus, i will not show the price of qty fall in 0 value when group by price.
id | id_item | qty | price
1 1 10 1.00
2 1 15 2.00
3 1 10 1.00
4 2 5 2.00
5 2 5 2.50
6 3 10 1.00
7 3 10 1.00
8 3 5 1.00
This is what i have tried.
Select id_item, price, sum(qty) as total from sales group by id_item, price having total !=0;
Result
id_item | qty | price
1 20 1.00
1 15 2.00
2 5 2.00
2 5 2.50
3 10 1.00
Expected result with concat
id_item | qty | price
1 20,15 1.00,2.00
2 5,5 2.00.2.50
3 10 1.00
How can i achieve the result as shown?
I think you need two levels of aggregation:
select id_item, group_concat(total order by price) as quantities,
group_concat(price order by price) as prices
from (Select id_item, price, sum(qty) as total
from sales
group by id_item, price
having total <> 0
) s
group by id_item;

MySQL Group By not producing expected result

This is my table structure:
rec_id product_id quantity quantity_in quantity_out balance stock_date status
1 2 342 NULL 17 325 2009-10-23 1
2 2 325 NULL 124 201 2009-10-23 1
3 1 156 NULL 45 111 2009-10-23 1
4 2 201 NULL 200 1 2009-10-23 1
5 2 1 NULL 1 0 2009-10-23 1
6 1 111 NULL 35 76 2009-10-23 1
All I want is the last transaction done for a given product: product_id, quantity, quantity_out and balance from this table.
Example, there are 2 transaction done for product 2 (ids 1 & 2):
final balance for product_id 2 is 0 -> stored in rec_id 5
final balance for product_id 1 is 76 -> stored in rec_id 6
Final result/output should be like this:
recid productid quantity quantityin quantityout balance stock_date status
5 2 1 NULL 1 0 2009-10-23 1
6 1 111 NULL 35 76 2009-10-23 1
You can find the latest record for each product like:
select max(rec_id) as MaxRec
from YourTable
group by product_id
Using a subquery, you can retrieve the latest rows for their product:
select *
from YourTable
where rec_id in (
select max(rec_id) as MaxRec
from YourTable
group by product_id
)
Here's a single query with no subqueries:
SELECT main.*
FROM YourTable main
LEFT JOIN YourTable newer
ON newer.product_id = main.product_id AND newer.rec_id > main.rec_id
WHERE newer.rec_id IS NULL;
You can tweak the field list however you want--make sure you select fields from main, not newer, which should be all null.