MySQL How to convert second group by parameter results as a column? - mysql

The following MySQL query result set repeats MerchantID:
select MerchantID,Category,SUM(Amount)
group by MerchantID,Category
from merchants
This will produce the following result:
MerchantID | Category | Total |
1 | gold | 450 |
1 | silver | 600 |
2 | gold | 1120 |
2 | bronze | 200 |
I want to get the result set like below:
MerchantID | gold | silver | bronze |
1 | 450 | 600 | 0 |
2 | 1120 | 0 | 200 |
I tried many queries but could not get such result. Please provide a solution for my problem. Thanks.

Use conditional aggregation:
select MerchantID,
SUM(CASE WHEN Category = 'gold' THEN Total ELSE 0 END) AS gold,
SUM(CASE WHEN Category = 'silver' THEN Total ELSE 0 END) AS silver,
SUM(CASE WHEN Category = 'bronze' THEN Total ELSE 0 END) AS bronze
from merchants
group by MerchantID
Demo here

You can use this code for example:
SELECT m.merchantId
sum(if(m.Category='gold',m.total,null)) as gold,
sum(if(m.Category='silver',m.total,null)) as silver,
sum(if(m.Category='bronze',m.total,null)) as bronze
FROM merchants m
GROUP BY m.merchantId

Related

MySQL Get the number of times values appear in a column?

In MySQL, I have a table that holds the outcomes of rounds of a contest. This table has a result column that contains the values 'won' 'lost' or 'draw'. How can I group by the competitor and get the counts of specific values? The idea is to be able to sort competitors based on the number of wins and losses, and calculate scores within the database query.
So, my table is:
+--------------+---------+--------+
| CompetitorId | MatchId | Result |
+--------------+---------+--------+
| 1 | 1 | won |
| 2 | 1 | lost |
| 1 | 2 | won |
| 3 | 2 | lost |
+--------------+---------+--------+
The result I am trying to get is:
+--------------+------+--------+
| CompetitorId | Wins | Losses |
+--------------+------+--------+
| 1 | 2 | 0 |
| 2 | 0 | 1 |
| 3 | 0 | 1 |
+--------------+------+--------+
The query I tried was this:
SELECT CompetitorId, COUNT(result='won') AS wins, COUNT(result='lost') AS losses
FROM match_competitors
GROUP BY CompetitorId
You can use sum with a case inside, giving a value of 1 when is the column you need and 0 when is not:
SELECT CompetitorId, sum(case result
when 'won' then 1
else 0
end) as wins,
sum(case result
when 'lost' then 1
else 0
end) as losses
FROM match_competitors
GROUP BY CompetitorId

Mysql display query data and count

Just an amateur here needing a little help.
I have a table named tbl_inspection_areas.area_description
columns 'area_description' and 'display_tab'.
I want a query that returns 'area_description','display_tab' and the number of times each display tab occurs.
Like in the drawing below.
| tbl_inspection_areas.area_description | tbl_inspection_areas.display_tab | count |
_____________________________________________________________________________________________
| engine | 38 | 2 |
| transmission | 38 | |
| interior | 39 | 1 |
| wheels | 40 | 3 |
| glass | 40 | |
| lights | 40 | |
This is the best I have come up with, but it only displays 3 rows and the count is in 3 seperate columns.
Any help would be great.
SELECT
tbl_inspection_areas.area_description,
tbl_inspection_areas.display_tab,
SUM(CASE WHEN tbl_inspection_areas.display_tab = '38' THEN 1 ELSE 0 END) AS count1,
SUM(CASE WHEN tbl_inspection_areas.display_tab = '39' THEN 1 ELSE 0 END) AS count2,
SUM(CASE WHEN tbl_inspection_areas.display_tab = '40' THEN 1 ELSE 0 END) AS count3,
SUM(CASE WHEN tbl_inspection_areas.display_tab = '46' THEN 1 ELSE 0 END) AS count4
FROM tbl_inspection_areas
GROUP BY tbl_inspection_areas.display_tab
SELECT
tbl_inspection_areas.area_description,
tbl_inspection_areas.display_tab,
COUNT(tbl_inspection_areas.display_tab)
FROM tbl_inspection_areas
GROUP BY tbl_inspection_areas.area_description,
tbl_inspection_areas.display_tab,

MySQL Crosstab aggregation with 2 conditions

I have a query which creates a crosstab. The results are a count of the txn_id for branda, and the count of txn_id for brandb.
The txn_id is NOT UNIQUE. This is an example of the transactions table.:
txn_id | nationality_id | sku | sales | units
1 | 1 | 1 | 20 | 2
1 | 1 | 2 | 15 | 1
2 | 4 | 1 | 20 | 2
3 | 2 | 1 | 10 | 1
4 | 3 | 2 | 15 | 1
5 | 4 | 1 | 10 | 1
There are 2 other tables (products) - (sku, brand, product name), and (nationalities) - (nationality_id, nationality).
I would like to add a third column which gets me the count of txn_id where BOTH brands are purchased
The output should be
nationality | branda | brandb | combined
1 | 1 | 1 | 1
2 | 1 | 0 | 0
3 | 0 | 1 | 0
4 | 2 | 0 | 0
Current query.
SELECT
nationalities.nationality,
COUNT((CASE brand WHEN 'branda' THEN txn_id ELSE NULL END)) AS branda,
COUNT((CASE brand WHEN 'brandb' THEN txn_id ELSE NULL END)) AS brandb
<I want my 3rd column here>
FROM
transaction_data
INNER JOIN
products USING (sku)
INNER JOIN
nationalities USING (nationality_id)
GROUP BY nationality
ORDER BY branda DESC
LIMIT 20;
I have tried using:
COUNT((CASE brand WHEN 'brandb' OR 'brandb' THEN txn_id ELSE NULL END)) AS combined - however this obviously returns too many (returns branda or brandb regardless of whether they were purchased together). I know I can't use AND, because obviously no single cell is going to be both branda AND brandb.
I have also tried using:
COUNT((CASE brand WHEN IN('branda', 'brandb') THEN txn_id ELSE NULL END)) AS combined - However this isn't valid syntax.
I feel that I should be using a HAVING clause, but I'm not sure how this would work in the column list.
I think you are going to need two levels of aggregation:
SELECT n.nationality,
sum(branda), sum(brandb), sum(branda * brandb)
FROM (SELECT t.txn_id, n.nationality,
MAX(CASE brand WHEN 'branda' THEN 1 ELSE 0 END) AS branda,
MAX(CASE brand WHEN 'brandb' THEN 1 ELSE 0 END) AS brandb
FROM transaction_data t INNER JOIN
products p
USING (sku) INNER JOIN
nationalities n
USING (nationality_id)
GROUP BY t.txn_id, n.nationality
) tn
GROUP BY n.nationality
ORDER BY max(txn_id) DESC
LIMIT 20;

MYSQL query display quantity of product from multiple tables

I have table like this
product :
id_product | product_name | price
560 | AAA | 1500
561 | BBB | 1750
attr :
id_attr | id_product | size | qty
100 | 560 | S | 11
100 | 560 | M | 9
100 | 560 | L | 7
100 | 560 | XL | 21
How to display
product_name | qty_S | qty_M | qty_L | qty_XL | qty_total | price
AAA | 11 | 9 | 7 | 21 | 48 | 1500
BBB | 0 | 0 | 0 | 0 | 0 | 1750
i try to make query like this :
select p.*, a.*,
sum(a.qty) as qty_total,
[how_to_display_query] as qty_S,
[how_to_display_query] as qty_M,
[how_to_display_query] as qty_L,
[how_to_display_query] as qty_XL,
FROM product p LEFT JOIN attr a
ON p.id_product = a.id_product
group by p.id_product;
===============================================
Please help me, sorry for bad english... Thanks
you want to pivot the results.. but you cant pivot in mysql as it doesn't have that functionality.. so you need to "fake" a pivot by using an aggregate and a conditional statement
the way to do that is like this.. MAX(CASE... ) SUM(CASE... ) etc.. can also be done with if MAX(IF... ) SUM(IF... ).
SELECT p.product_name
SUM(a.qty) as qty_total,
MAX(CASE size WHEN 'S' THEN qty ELSE 0 END) as qty_S,
MAX(CASE size WHEN 'M' THEN qty ELSE 0 END) as qty_M,
MAX(CASE size WHEN 'L' THEN qty ELSE 0 END) as qty_L,
MAX(CASE size WHEN 'XL' THEN qty ELSE 0 END) as qty_XL,
p.price
FROM product p
LEFT JOIN attr a ON p.id_product = a.id_product
GROUP BY by p.id_product;
i used MAX() here because you only seem to be getting one number.. if you were wanting to add multiple quantities then you can change MAX to SUM

Transform datas in MySQL

I've got a query like this
select company, extract(week from date) as week, sum(value)
from temporary GROUP BY company,yearweek(date)
and after I got a view
Company | Week | Value
Dunaferr | 1 | 310
Dunaferr | 2 | 220
Dunaferr | 3 | 310
Pentele-Invest| 1 | 450
Pentele-Invest| 2 | 543
Pentele-Invest| 3 | 344
Finally what I want to is a table which one is sums the values weekly which is ordered by the company names
company_name | week1 | week2 | week3 | week4 ...
dunaferr | 35000 | 36000 | 28000 | 3411
pentele | 34000 | 255000 | 3341 | 3433
And I know there is a way to use pivoting but I don't know how to do it.
select szallito_nev,
sum(case extract(week from beerkezes_datuma) when '1' then merlegelt_suly else 0 end) as 'Het 1',
sum(case extract(week from beerkezes_datuma) when '2' then merlegelt_suly else 0 end) as 'Het 2',
sum(case extract(week from beerkezes_datuma) when '3' then merlegelt_suly else 0 end) as 'Het 3',
from 2013_backup GROUP BY szallito_nev with rollup;
i'll tried this one its work well but not so elegant way to do it:S becouse i have to go throw all the weeks of the year. probably theres a way to do it with loop