Min and Max from every group - php

I have two table
location:
location_id
address
itransfile:
id
transactionNumber
location_id
itemName
quantity
I want to get maximum and minimum sold items by locations.
HighestItemName HighQauntity LowestItemName LowQuantity LocationName
Chicken Burger 50 Tako 5 Gulshan
Chicken Burger 100 Tikka 10 Nipa
Pasta 150 Cheese Burger 12 Liyari
Pizza 200 Chicken Burger 3 F.B.Area
The query I've done so far:
SELECT t.itemName as HighestItemName, sum(t.quantity) as HighQuantity, l.address LocationName
from itransfile as t join locations as l
on t.location_id = l.location_id
where t.location_id IN(1,2,3,4)
group by t.location_id
I don't know how will get max and min items from every group.
Sample Data:
ID TransNumber ItemName Quantity location_id
1 1234 Chicken Burger 3 1
2 1234 Cheese Burger 1 1
3 1235 Sandwich 4 2
4 1332 Salad 1 4
5 14537 Tikka 1 3
6 1236 Roll 3 2
7 1333 Biryani 2 4
location_id address
1 Gulshan
2 Nipa
3 Liyari
4 F.B.Area

This is what you may be looking for if you need it in one query (SQLFiddle):
select
l.address,
imax.itemName max_item, max_min.max_q,
imin.itemName min_item, max_min.min_q
FROM
(select
i.location_id, MAX(i.quantity) max_q, MIN(i.quantity) min_q
FROM
itransfile i
GROUP BY
i.location_id) as max_min
LEFT JOIN itransfile imax ON (max_min.max_q = imax.quantity)
LEFT JOIN itransfile imin ON (max_min.min_q = imin.quantity)
LEFT JOIN location l ON (max_min.location_id = l.location_id)
GROUP BY
l.location_id
It looks for min/max values and then looks up the item name and location address. The GROUP_CONCAT makes sure that when there are more items with the same min/max quantity, you get all of them.
Alternatively you can get rid of the GROUP BY and GROUP_CONCAT and get all the items in rows if you need to further process them.

Related

codeigniter: get percentage in multiple table by data category

I have tables like this,
table_a
PID Name Type
1 a selling
2 b sampling
3 c selling
4 d sampling
5 e selling
And,
table_b
ID PID Qty
1 2 3
2 2 2
3 1 1
4 3 1
5 1 3
6 5 3
7 4 3
8 3 2
I need to show like this,
output_selling
Name Total_qty Percentage
a 4 40%
c 3 30%
e 3 30%
And,
output_sampling
Name Total_qty Percentage
b 5 62,5%
d 3 37,5%
How would I go about this in CodeIgniter?
You can use below in your function and change 'sampling' and 'selling' as you need it:
$this->db->query("
SELECT dd.NAME,
dd.total_qty,
( dd.total_qty / dd.totals ) * 100 AS Percentage
FROM (SELECT a.NAME,
Sum(b.qty) AS Total_qty,
(SELECT Sum(b1.qty) AS total
FROM table_b b1
JOIN table_a a1
ON a1.pid = b1.pid
AND a1.type = 'selling') AS totals
FROM table_a a
JOIN table_b b
ON b.pid = a.pid
AND a.type = 'selling'
GROUP BY a.pid) dd ");
Please see below query output:

How to count a Column data using join over 3 tables

I have three tables
tbl_product
item_id | item_name
company_details
v_id | item_id | company_name
user_ratings
r_id | rate | v_id
I want to count the rate and also get the rate of the company. Here is my query
SELECT company_details.v_id,
company_details.company_name,
COUNT(user_ratings.rate) as vote,
user_ratings.rate,
tbl_product.item_name
FROM company_details
LEFT JOIN tbl_product ON tbl_product.item_id = company_details.item_id
LEFT JOIN user_ratings ON user_ratings.v_id = company_details.v_id
GROUP BY company_details.v_id, user_ratings.rate
This is Whts i am Getting after this query:
v_id company_name vote rate item_name
1 The Oberoi Udaivilas 1 4 5 Star Hotels
1 The Oberoi Udaivilas 1 5 5 Star Hotels
2 The Taj Mahal Palace 2 5 4 Star Hotels
3 Rambagh Palace 1 5 3 Star Hotels
4 Taj Lake Palace 1 5 5 Star Hotels
5 Windflower Hall 1 3 2 Star Hotels
5 Windflower Hall 1 5 2 Star Hotels
6 Leela Palace Kempinski 0 n 4 Star Hotels
7 Umaid Bhawan Palace 0 n 4 Star Hotels
8 Hotel Ratan Vilas 0 n 4 Star Hotels
9 The Leela Palace 0 n 4 Star Hotels
10 The Imperial Hotel 0 n 3 Star Hotels
You can see vote column is not counting.
This is what I am expecting
v_id company_name vote rate item_name
1 The Oberoi Udaivilas 2 5 5 Star Hotels
2 The Taj Mahal Palace 2 5 4 Star Hotels
But this query is not counting the rate from user_ratings table, because of I also want to get the rate, if I remove the user_ratings.rate from select clause, then this query works, but when I add the user_ratings.rate in the select clause, then this query is not counting the rates as(vote), and it is returning as one rows in every count.
You should remove user_ratings.rate from group by clause and add tbl_product.item_name.
SELECT
company_details.v_id,
company_details.company_name,
tbl_product.item_name,
COUNT(user_ratings.rate) as vote,
avg(user_ratings.rate) as rate
FROM
company_details
LEFT JOIN tbl_product ON tbl_product.item_id = company_details.item_id
LEFT JOIN user_ratings ON user_ratings.v_id = company_details.v_id
GROUP BY company_details.v_id, company_details.company_name, tbl_product.item_name;
Seems to me that your query is only missing an aggregation on the rate column, and from the expected output I'd say it's a max. You also should fix your group by. Try this one
SELECT company_details.v_id,
company_details.company_name,
COUNT(user_ratings.rate) as vote,
MAX(user_ratings.rate) as rate,
tbl_product.item_name
FROM company_details
LEFT JOIN tbl_product ON tbl_product.item_id = company_details.item_id
LEFT JOIN user_ratings ON user_ratings.v_id = company_details.v_id
GROUP BY company_details.v_id,
company_details.company_name,
tbl_product.item_name
Query and result are both correct. Look at the rate
you can try this query it will return your exactly output according to your given 3 tables.
"select c.v_id , c.company_name , u.rate , p.item_name from company_details c join tbl_product p on p.item_id = c.item_id join user_details u on c.v_id = u.v_id group by c.company_name ";

Mysql: Duplicate and incorrect output when using join

I have 4 tables on which I need to use a join. The query is returning duplicate rows. However for simplicity I will post my question with just 2 tables as the problem still exits even with 2 tables. Tables are called as product_offer and promo. The structures are as below
product_offer table:
id product_id offer_id store_id validity
1 1 1 1 2016-12-12 00:00:00
2 2 2 1 2016-12-12 00:00:00
3 3 3 1 2016-12-12 00:00:00
4 1 4 1 2016-12-12 00:00:00
promo table:
id product_id store_id name
1 1 1 Buy 1 Get 1 free
2 2 1 10% off
3 3 1 $10 off
4 1 1 Get Chips Free
I am trying to fetch all the offers for a particular product-store combination. I am expecting to get this
product_id offer_id store_id name
1 1 1 Buy 1 Get 1 Free
1 4 1 Get Chips Free
But When I run this query I am getting the below output which is incorrect and with duplicate rows
SELECT po.product_id, po.offer_id,po.store_id,o.name
from product_offer po
left join promo o on po.product_id = o.product_id
where po.product_id = 1 and po.store_id = 1
product_id offer_id store_id name
1 1 1 Buy 1 Get 1 Free
1 4 1 Buy 1 Get 1 Free
1 1 1 Get Chips Free
1 4 1 Get Chips Free
I also want to improve the query and use concat(using ~ as separator) to only return one row per product_id as below:
product_id offer_id store_id name
1 1~4 1 Buy 1 Get 1 free~Get Chips Free
You want to use a GROUP BY, what does it, it takes the column you chose puts them together to avoid duplicate results where data in that column matches
SELECT po.product_id, po.offer_id,po.store_id,o.name
from product_offer po
left join promo o on po.product_id = o.product_id
where po.product_id = 1 and po.store_id = 1
GROUP BY product_id
In order to concatenate them, there is the option of GROUP_CONCAT, you can read more at http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat
use Group by with GROUP_CONCAT
SELECT po.product_id,GROUP_CONCAT(DISTINCT po.offer_id SEPARATOR '~') offer_id
,po.store_id,GROUP_CONCAT(DISTINCT o.name SEPARATOR '~') name
from product_offer po
left join promo o on po.product_id = o.product_id
where po.product_id = 1 and po.store_id = 1
Group by product_id
I realized I was doing the Join ON the wrong column. When I changed the join on offer_id from product_offer and id on promo it worked nicely.
SELECT po.product_id, group_concat(po.offer_id SEPARATOR '~') offer_id, po.store_id ,group_concat(o.name SEPARATOR '~') offer
FROM product_offer po
LEFT JOIN
promo o ON po.offer_id = o.id
WHERE
po.product_id = 1 and po.store_id = 1
I think you need to group by offer_id
SELECT po.product_id,GROUP_CONCAT(po.offer_id SEPARATOR '~') offer_id,po.store_id,o.name
from product_offer po
left join promo o on po.product_id = o.product_id
where po.product_id = 1 and po.store_id = 1
Group by offer_id

mysql join and sum problems

Im having some trouble with this.
Here's an example of my tables.
Booking
id zone_id name excursion_id
1 2 1
2 1 1
3 2 1
The table where I have the quantities
booking_price
id_booking id_price quantity
1 1 2
1 2 3
2 1 1
2 2 0
3 1 2
3 2 3
Here the zone table
Zone
id Name
1 a
2 b
3 c
So I want to have a table like that
Zone_id Quantity
1 1
2 10
3 0
The problem is when im joining tables and filtering by excursion_id im not getting ALL the zones.
I want to know how many people goes in each zone.
I think better way of doing it is
select z.id, coalesce(sum(bp.quantity),0) as quantity
from Booking b
right join Zone z on z.id = b.zone_id AND b.excursion_id = 1
left join booking_price bp on bp.id_booking = b.id
group by z.id
demo http://sqlfiddle.com/#!2/771f5/13
You could use a query like:
SELECT zone.id as zone_id,
sum(quantity) as Quantity
FROM zone
LEFT JOIN Booking on Booking.zone_id = zone.id
LEFT JOIN Excursion on Excursion.id_booking = Booking.id
GROUP BY zone.id

A simple mySQL statement to ask

I've a question to ask about mysql, I am creating a supplier page which requires list down all the suppliers details and their products (randomly choose 3 product for each supplier), so we have to join 2 tables together, one is suppliers, another one is products, may I know how to present them in single mysql statement?
table1 - suppliers
id corp_name product_count
---------------------------------------
AD0728 John Smith 187
AD0729 JayJay 1983
table2 - products
pid cid p_name quantity
---------------------------------------
1 AD0728 Body Shampoo 10
2 AD0728 glass 10
3 AD0728 pen 10
4 AD0728 pencil 10
5 AD0728 eraser 10
6 AD0728 speaker 10
7 AD0729 monitor 10
8 AD0729 keyboard 10
9 AD0729 mouse 10
10 AD0729 processor 10
11 AD0729 box 10
12 AD0729 sunglass 10
Output
id corp_name pid p_name quantity
----------------------------------------------------------------
AD0728 John Smith 1 Body Shampoo 10
AD0728 John Smith 2 glass 10
AD0728 John Smith 3 pen 10
AD0729 JayJay 10 processor 10
AD0729 JayJay 11 box 10
AD0729 JayJay 12 sunglass 10
Thanks everyone.
For SQL Server 2005 or greater you can use ORDER BY NEWID() for a random order and you can use ROW_NUMBER to get your partion:
WITH CTE AS
(
SELECT
s.id, s.corp_name, p.pid, p.p_name, p.quantity
, RN = ROW_NUMBER() OVER (PARTITION BY s.id ORDER BY NEWID())
FROM suppliers s
INNER JOIN products p ON s.id = p.cid
)
SELECT id, corp_name, pid, p_name, quantity
FROM CTE WHERE RN <= 3
Here's the fiddle (thanks to #MahmoudGamal): http://www.sqlfiddle.com/#!3/a26c6/17/0
Check this SQL Fiddle code. It will return as requested the first 3 products for each supplier. It will work for SQL2005 and greater as it uses CTE (Common Table Expressions), introduced with SQL2005.
Either ways, here is the code:
;WITH myCTE AS (
SELECT p.*, ROW_NUMBER() OVER (PARTITION BY p.cid ORDER BY NEWID()) AS r
FROM products p)
SELECT sup.id,sup.corp_name,c.pid,c.p_name,c.quantity
FROM myCTE c JOIN suppliers sup ON c.cid = sup.id
WHERE c.r <= 3
In MYSQL this works: http://sqlfiddle.com/#!2/8b291/10
SET #rank=0;
SELECT *, #rank:=#rank+1 AS rank
FROM suppliers s
LEFT JOIN products p ON p.cid = s.id
GROUP BY s.id, #rank % 3

Categories