join 2 table with SUM and Group By - php

i have 2 table one is buy_table and another is sale_table. in this query in this query i will have to use SUM , group by and date also but i am not able to understand and its showing som error
//buy table
----------------------------------------------------------
| id | product_id | quantity | total_price | date |
----------------------------------------------------------
| 1 | 1 | 5 | 500 | 2014-12-05 |
----------------------------------------------------------
| 2 | 2 | 5 | 500 | 2014-12-15 |
----------------------------------------------------------
| 3 | 1 | 5 | 500 | 2014-12-01 |
//Sale_table
----------------------------------------------------------
| id | product_id | quantity | total_price | date |
----------------------------------------------------------
| 1 | 1 | 5 | 1800 | 2014-12-05 |
----------------------------------------------------------
| 2 | 2 | 5 | 500 | 2014-12-15 |
----------------------------------------------------------
| 3 | 3 | 5 | 500 | 2015-01-01 |
----------------------------------------------------------
| 4 | 3 | 5 | 500 | 2015-01-01 |
i need like this.
----------------------------------------------------------------------
| id | product_id |buy_quantity| buy_total | sale_quantity|sale_total
----------------------------------------------------------------------
| 1 | 1 | 10 | 1000 | 5 | 1800
----------------------------------------------------------------------
| 2 | 2 | 5 | 500 | 5 | 500
----------------------------------------------------------------------
| 3 | 3 | 5 | 500 | 10 | 1000
----------------------------------------------------------------------

SELECT
A.ID,A.PRODUCT_ID,A.BUY_QUANTITY,B.SALE_QUANTITY,A.BUY_TOTAL,B.SALE_TOTAL,A.DATE
(select id,product_id,sum(quantity) as buy_quantity,sum(total_price) as
buy_total,date from buy_table group by product_id) A INNER JOIN (SELECT sum
(quantity) as SALE_quantity,sum(total_price) as SALE_total FROM SALE_TABLE group by product_id) B
ON A.PRODUCT_ID=B.PRODUCT_ID

I will suppose that you mistyped the third row in buy table and you meant to type 3 in product_id and the id column in the desired result set is just a serial which is not relevant to any data. The below query might be the answer for your inquiry:
-- Simluating your tables
DECLARE #buyTable AS TABLE (id INT, product_id INT, quantity INT, total_price INT, date DATE)
DECLARE #saleTable AS TABLE (id INT, product_id INT, quantity INT, total_price INT, date DATE)
INSERT INTO #buyTable
VALUES(1, 1, 5, 500, '2014-12-05'), (2, 2, 5, 500, '2014-12-15'), (3, 3, 5, 500, '2014-12-01')
INSERT INTO #saleTable
VALUES(1, 1, 5, 1800, '2014-12-05'), (2, 2, 5, 500, '2014-12-15'), (3, 3, 5, 500, '2014-01-01'), (4, 3, 5, 500, '2015-01-01')
-- Simluation stops here
SELECT ROW_NUMBER() OVER(ORDER BY b.product_id) AS id, b.product_id, buy_quantity, buy_total, sale_quantity, sale_total FROM
(
SELECT product_id, SUM(quantity) AS buy_quantity, SUM(total_price) AS buy_total FROM #buyTable
GROUP BY product_id
) b
INNER JOIN
(
SELECT product_id, SUM(quantity) AS sale_quantity, SUM(total_price) AS sale_total FROM #saleTable
GROUP BY product_id
) s ON s.product_id = b.product_id

The id column in your results doesn't make sense if you want to show buy/sale by product.
To ensure you always get all the products, you need to use your product table as the driving table (Assuming you have a product table)
select
p.product_id,
(SELECT SUM(b.quantity) FROM buy b WHERE b.product_id = p.product_id) as buy_quantity,
(SELECT SUM(b.total_price) FROM buy b WHERE b.product_id = p.product_id) as buy_total,
(SELECT SUM(s.quantity) FROM sale s WHERE s.product_id = p.product_id) as sale_quantity,
(SELECT SUM(s.total_price) FROM sale s WHERE s.product_id = p.product_id) as sale_total
from product p

Related

How to select unique value from many to many mysql relationship

Hi I got confused in this sql case. I am using mysql Ver 15.1 Distrib 10.2.31-MariaDB. And let's say I have 3 table products, categories, and product_categories as pivot table.
Here is the data example:
products:
| id | name |
------------------------
| 1 | asd wef |
| 2 | gggg2222 |
| 3 | pppga 99 |
| 4 | lalala 55 |
And for categories:
| id | level | parent_id | name |
-----------------------------------
| 20 | 1 | | Fashion |
| 22 | 2 | 20 | Top |
| 23 | 3 | 22 | T-Shirt |
| 24 | 3 | 22 | Jacket |
And for the pivot table, product_categories:
| product_id | category_id |
--------------------------------
| 1 | 20 |
| 1 | 22 |
| 1 | 23 |
| 2 | 22 |
| 2 | 20 |
| 3 | 20 |
| 4 | 20 |
So as you can see from pivot table only product_id = 3 & 4 that stop in category level 1. And product_id = 2 only stop in category level 2.
What I would like to achieve here is when I select from categories table. I can count how many product that stopping here. This is example of the data that I want to get.
"categories": [
{
"id": 20,
"total_product": 4
"stopped_product": 2
},
{
"id": 22,
"total_product": 3
"stopped_product": 1
}
]
So far I tried using group by:
SELECT * FROM product_categories WHERE product_id IN (1, 2, 3, 4) GROUP BY product_id HAVING category_id=20
output:
| product_id | category_id |
--------------------------------
| 1 | 20 |
| 3 | 20 |
| 4 | 20 |
Expected Output
| product_id | category_id |
--------------------------------
| 3 | 20 |
| 4 | 20 |
You can use a CTE to generate a list of stop categories for each product and then JOIN that to the categories and product_categories tables to count the total number of products and number of stopped products for each category:
WITH prods AS (
SELECT product_id, MAX(category_id) AS stop_cat
FROM product_categories
GROUP BY product_id
)
SELECT c.id AS category_id,
COUNT(DISTINCT pc.product_id) AS total_product,
SUM(c.id = p.stop_cat) AS stopped_product
FROM categories c
JOIN product_categories pc ON pc.category_id = c.id
JOIN prods p ON p.product_id = pc.product_id
GROUP BY c.id
Output (for your sample data)
category_id total_product stopped_product
20 4 2
22 2 1
23 1 1
Demo on dbfiddle
I guess you want max values only
SELECT product_id,MAX(category_id) as category_id FROM product_categories WHERE product_id IN (1, 2,
3, 4)
GROUP BY product_id
HAVING category_id=20
Here is you can find category-wise product count and ids:
SELECT c.name as categoryName, c.level, COUNT(pc.product_id) as productCount, GROUP_CONCAT(pc.product_id) as productIds
FROM product_categories pc JOIN categories c ON c.id = pc.category_id
WHERE 1
GROUP by c.id

Mysql sort the results based on 2 columns from different tables

I have 2 tables with the following structure
Products
id | name | created_at |
1 | Produt1 | 2019-11-01 19:05:56 |
2 | Product 2 | 2020-01-28 19:05:56 |
3 | Product 3 | 2020-01-26 19:05:56 |
Draws
id | product_id |draw_number | created_at |
1 | 1 | 1 | 2020-01-28 19:05:56 |
2 | 1 | 2 | 2020-01-27 19:05:56 |
The scenario is, we have 3 products in product table and for product 1, we have 2 entries in draws table.
I am looking for a query here that selects the data from products table and data should be ordered by
If draws created_at exists, then order by draw created at
If no draws, sort by created at of products table.
Result output should be like this
id | name | created_at |
1 | Produt1 | 2019-01-28 19:05:56 | //created_at of draws of latest draw for this product
2 | Product 2 | 2020-01-28 19:05:56 |
3 | Product 3 | 2020-01-26 19:05:56 |
How can I selected the expected data?
TIA
Test
SELECT t1.*
FROM Products t1
LEFT JOIN ( SELECT t2.product_id,
MAX(t2.created_at) created_at
FROM Draws t2
GROUP BY product_id ) t3 ON t1.id = t3.product_id
ORDER BY GREATEST(t1.created_at, t3.created_at) DESC
This give you the wanted result
CREATE TABLE Draws
(`id` int, `product_id` int, `draw_number` int, `created_at` datetime)
;
INSERT INTO Draws
(`id`, `product_id`, `draw_number`, `created_at`)
VALUES
(1, 1, 1, '2020-01-28 19:05:56'),
(2, 1, 2, '2020-01-27 19:05:56')
;
✓
✓
CREATE TABLE Products
(`id` int, `name` varchar(9), `created_at` datetime)
;
INSERT INTO Products
(`id`, `name`, `created_at`)
VALUES
(1, 'Produt1', '2019-11-01 19:05:56'),
(2, 'Product 2', '2020-01-28 19:05:56'),
(3, 'Product 3', '2020-01-26 19:05:56')
;
✓
✓
SELECT p.id,p.name,MAX( IFNULL(d.`created_at` , p.`created_at`))
FROM Draws d RIGHT JOIN Products p
ON d.product_id = p.id
GROUP BY p.id,p.name
ORDER BY p.id;
id | name | MAX( IFNULL(d.`created_at` , p.`created_at`))
-: | :-------- | :--------------------------------------------
1 | Produt1 | 2020-01-28 19:05:56
2 | Product 2 | 2020-01-28 19:05:56
3 | Product 3 | 2020-01-26 19:05:56
db<>fiddle here

How to get data for two columns using right join with MYSQL case

I want to get the categories pricing, Say if there is data in customer_category_pricing table then fetch that pricing for that specific customer. Otherwise fetch default prices from categories table.
i have tried achieving this desired result using mysql case it is working fine, but the problem is, it is returning two rows
hourly_amount_final column returns updated price then per_day_amount_final returns default price
Then in next row, hourly_amount_final column return default price and then per_day_amount_final returns updated price.
table: pr_categories
---------------------------------------------------------------------------------
| id | title | hourly_amount | per_day_amount | created_at| updated_at
---------------------------------------------------------------------------------
| 1 | Power Generation | 100.00 | 200.00 |
| 2 | Local Government | 300.00 | 400.00 |
----------------------------------------------------------
table: pr_customer_categories_pricing
------------------------------------------------------------------------------------
| id | customer_id | category_id | billing_type_id | amount | created_at | updated_at
------------------------------------------------------------------------------------
| 1 | 1 | 1 | 1 | 109 |
| 2 | 1 | 1 | 2 | 600 |
----------------------------------------------------------
table: pr_billing_types
----------------
| id | title |
--------------
| 1 | Hourly |
| 2 | Per Day |
----------------
This is the query i am working with at the moment:
SELECT c.id,c.title,
CASE
WHEN (c.hourly_amount <> (SELECT ccp.amount WHERE ccp.billing_type_id = 1))
THEN (SELECT ccp.amount WHERE ccp.billing_type_id = 1)
ELSE c.hourly_amount
END
AS hourly_amount_final,
CASE
WHEN (c.per_day_amount <> (SELECT ccp.amount WHERE ccp.billing_type_id = 2))
THEN (SELECT ccp.amount WHERE ccp.billing_type_id = 2)
ELSE c.per_day_amount
END
AS per_day_amount_final
FROM pr_customer_category_pricing AS ccp
RIGHT JOIN pr_categories AS c
ON c.id = ccp.category_id AND ccp.customer_id = 1
Expected result when there is no data in pr_customer_category_pricing
----------------------------------------------------------------------
| id | title | hourly_amount_final | per_day_amount_final |
----------------------------------------------------------------------
| 1 | Power Generation | 100.00 | 200.00 |
| 2 | Local Government | 300.00 | 600.00 |
----------------------------------------------------------------------
Expected result when there is data in pr_customer_category_pricing
----------------------------------------------------------------------
| id | title | hourly_amount_final | per_day_amount_final |
----------------------------------------------------------------------
| 1 | Power Generation | 109.00 | 600.00 |
| 2 | Local Government | 300.00 | 400.00 |
----------------------------------------------------------------------
Actual result what i'm getting:
----------------------------------------------------------------------
| id | title | hourly_amount_final | per_day_amount_final |
----------------------------------------------------------------------
| 1 | Power Generation | 109.00 | 200.00 |
| 1 | Power Generation | 100.00 | 600.00 |
| 2 | Local Government | 300.00 | 400.00 |
----------------------------------------------------------------------
What am i doing wrong? Any suggestions! Help a brother out. :S
Since there can only be one entry in the pr_customer_category_pricing table per billing type, you can simplify things by creating a derived pivot table from the pr_customer_category_pricing with values for each of the billing_type_id in separate columns. You can then simply COALESCE the value from the derived table with the value from the pr_categories for each billing_type_id:
SELECT c.id,c.title,
COALESCE(ccp.hourly_amount, c.hourly_amount) AS hourly_amount_final,
COALESCE(ccp.per_day_amount, c.per_day_amount) AS per_day_amount_final
FROM (SELECT
customer_id,
category_id,
MAX(CASE WHEN billing_type_id = 1 THEN amount END) AS hourly_amount,
MAX(CASE WHEN billing_type_id = 2 THEN amount END) AS per_day_amount
FROM pr_customer_category_pricing
GROUP BY customer_id, category_id) AS ccp
RIGHT JOIN pr_categories AS c
ON c.id = ccp.category_id AND ccp.customer_id = 1
Output:
id title hourly_amount_final per_day_amount_final
1 Power Generation 109 600
2 Local Government 300 400
Demo on dbfiddle
You can use max() aggregation with group by
SELECT c.id,c.title,
max(CASE
WHEN (c.hourly_amount <> (SELECT ccp.amount WHERE ccp.billing_type_id = 1))
THEN (SELECT ccp.amount WHERE ccp.billing_type_id = 1)
ELSE c.hourly_amount
END)
AS hourly_amount_final,
max(CASE
WHEN (c.per_day_amount <> (SELECT ccp.amount WHERE ccp.billing_type_id = 2))
THEN (SELECT ccp.amount WHERE ccp.billing_type_id = 2)
ELSE c.per_day_amount
END)
AS per_day_amount_final
FROM pr_customer_category_pricing AS ccp
RIGHT JOIN pr_categories AS c
ON c.id = ccp.category_id AND ccp.customer_id = 1
group by c.id,c.title

Stuck in building MySQL query

Given an example of table:
id | item_id | user_id | bid_price
----------------------------------
The task is to select rows with minimum bid_price for each item_id in the provided set.
For example: item_id = [1, 2, 3] - so I need to select up to three (3) rows, having a minimum bid_price.
Example of data:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
2 | 1 | 12 | 2
3 | 1 | 13 | 3
4 | 1 | 14 | 1
5 | 1 | 15 | 4
6 | 2 | 16 | 2
7 | 2 | 17 | 1
8 | 3 | 18 | 2
9 | 3 | 19 | 3
10 | 3 | 18 | 2
Expected result:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
7 | 2 | 17 | 1
8 | 3 | 18 | 2
Actually, I'm using Symfony/Docine DQL, but it will be enough with a plain SQL example.
For the all the columns in the rows you could use a inner join on subselect for min bid price
select m.id, m.item_id, m.user_id, m.bid_price
from my_table m
inner join (
select item_id, min(id) min_id, min(bid_price) min_price
from my_table
where item_id IN (1,2,3)
group by item_id
) t on t.item_id = m.item_id
and t.min_price= m.bid_price
and t.min_id = m.id
or .. if you have some float data type you could use a acst for unsigned
select m.id, m.item_id, m.user_id, cast(m.bid_price as UNSIGNED)
from my_table m
inner join (
select item_id, min(id) min_id, min(bid_price) min_price
from my_table
where item_id IN (1,2,3)
group by item_id
) t on t.item_id = m.item_id
and t.min_price= m.bid_price
and t.min_id = m.id
You can use MIN() with GROUP BY in the query:
SELECT id, item_id, MIN(bid_price) AS min_bid, user_id
FROM your_tbl
GROUP BY item_id
HAVING item_id in(1, 2, 3);
Use this query:
SELECT id, item_id, user_id, min(bid_price) as bid_price
FROM YOUR_TABLE_NAME
GROUP BY item_id;

How to get father name in php

I have a sample code:
products(id, parent_id, name)
1 | 0 | product1
2 | 0 | product2
3 | 1 | product1_1
4 | 1 | product1_2
5 | 2 | product2_1
6 | 2 | product2_2
And query:
SELECT prod.id, prod.name
FROM `products` AS prod
INNER JOIN `products` AS prod_parent ON prod_parent.product_id = prod.parent_id
But result is:
3 | product1_1
4 | product1_2
5 | product2_1
6 | product2_2
How to get parent father
1 | product1
2 | product2
Be specific in your SELECT list which table you want them from. This will give you all four columns, but you can trim it to only those you need.
SELECT
prod.id AS prod_id,
prod.name AS prod_name,
prod.parent_id AS parent_id,
prod_parent.name AS parent_name
FROM `products` AS prod
LEFT JOIN `products` AS prod_parent ON prod_parent.product_id = prod.parent_id

Categories