How to get the transposition of a table in mysql [duplicate] - mysql

This question already has answers here:
How can I return pivot table output in MySQL?
(10 answers)
Closed 9 years ago.
i have problem with transposing row to column and column to row.
I can do that if it just transpose row to column or column to row.
This my table with data
UNIT|JAN|FEB|MAR|APR|MEI|JUN
CS-1|100|200|300|400|500|600
CS-2|111|222|333|444|555|666
CS-3|331|123|423|923|918|123
and I would like to get the following output
MONTH|CS-1|CS-2|CS-3
JAN |100 |111 |331
FEB |200 |222 |123
MAR |300 |333 |423
etc..
Anybody know how to do this? Thanks very much!

You can do it this way
SELECT month,
MAX(CASE WHEN unit = 'CS-1' THEN value END) `CS-1`,
MAX(CASE WHEN unit = 'CS-2' THEN value END) `CS-2`,
MAX(CASE WHEN unit = 'CS-3' THEN value END) `CS-3`
FROM
(
SELECT unit, month,
CASE month
WHEN 'JAN' THEN jan
WHEN 'FEB' THEN feb
WHEN 'MAR' THEN mar
WHEN 'APR' THEN apr
WHEN 'MAY' THEN may
WHEN 'JUN' THEN jun
END value
FROM table1 t CROSS JOIN
(
SELECT 'JAN' month UNION ALL
SELECT 'FEB' UNION ALL
SELECT 'MAR' UNION ALL
SELECT 'APR' UNION ALL
SELECT 'MAY' UNION ALL
SELECT 'JUN'
) c
) q
GROUP BY month
ORDER BY FIELD(month, 'JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN')
Output:
| MONTH | CS-1 | CS-2 | CS-3 |
|-------|------|------|------|
| JAN | 100 | 111 | 331 |
| FEB | 200 | 222 | 123 |
| MAR | 300 | 333 | 423 |
| APR | 400 | 444 | 923 |
| MAY | 500 | 555 | 918 |
| JUN | 600 | 666 | 123 |
Here is SQLFiddle demo

Related

SQL Query Calculate Quarterly data from monthly data [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have table given below
Year Month Pro Revenue
2019 | Jan | ABC | 1200
2019 | Feb | ABC | 2451
2019 | Mar | ABC | 6543
2019 | Apr | ABC | 3987
2019 | May | ABC | 4097
2019 | Jun | ABC | 4587
2019 | Jul | ABC | 3878
2019 | Aug | ABC | 1098
2019 | Sep | ABC | 3201
2019 | Oct | ABC | 1209
2019 | Nov | ABC | 4398
2019 | Dec | ABC | 4517
Can someone pls help me here, i am not able to create a sql query for the following
which quarter has the best revenue?
SELECT SUM(C.REVENUE)S_REVENUE,
CASE
WHEN C.MONTH IN('Jan','Feb','Mar') THEN 1
WHEN C.MONTH IN('Apr','May','Jun')THEN 2
WHEN C.MONTH IN('Jul','Aug','Sep')THEN 3
ELSE 4
END AS QUART
FROM YOUR_TABLE AS C
GROUP BY
CASE
WHEN C.MONTH IN('Jan','Feb','Mar') THEN 1
WHEN C.MONTH IN('Apr','May','Jun')THEN 2
WHEN C.MONTH IN('Jul','Aug','Sep')THEN 3
ELSE 4
END
Another option would be:
DECLARE #Revenue table ( [Year] int, [Month] varchar(3), Pro varchar(3), Revenue decimal(18,2) );
INSERT INTO #Revenue VALUES
( 2019, 'Jan', 'ABC', 1200 ),
( 2019, 'Feb', 'ABC', 2451 ),
( 2019, 'Mar', 'ABC', 6543 ),
( 2019, 'Apr', 'ABC', 3987 ),
( 2019, 'May', 'ABC', 4097 ),
( 2019, 'Jun', 'ABC', 4587 ),
( 2019, 'Jul', 'ABC', 3878 ),
( 2019, 'Aug', 'ABC', 1098 ),
( 2019, 'Sep', 'ABC', 3201 ),
( 2019, 'Oct', 'ABC', 1209 ),
( 2019, 'Nov', 'ABC', 4398 ),
( 2019, 'Dec', 'ABC', 4517 );
SELECT
Qtr,
SUM ( [Revenue] ) AS QtrRev
FROM #Revenue
CROSS APPLY (
SELECT DATEPART ( quarter, CAST (
CASE [Month]
WHEN 'Jan' THEN '1'
WHEN 'Feb' THEN '2'
WHEN 'Mar' THEN '3'
WHEN 'Apr' THEN '4'
WHEN 'May' THEN '5'
WHEN 'Jun' THEN '6'
WHEN 'Jul' THEN '7'
WHEN 'Aug' THEN '8'
WHEN 'Sep' THEN '9'
WHEN 'Oct' THEN '10'
WHEN 'Nov' THEN '11'
WHEN 'Dec' THEN '12'
END + '/01/' + CAST ( [Year] AS varchar(4) ) AS date ) ) AS Qtr
) AS Qtr
WHERE
[Year] = 2019
GROUP BY Qtr
ORDER BY
QtrRev DESC;
Which returns
+-----+----------+
| Qtr | QtrRev |
+-----+----------+
| 2 | 12671.00 |
| 1 | 10194.00 |
| 4 | 10124.00 |
| 3 | 8177.00 |
+-----+----------+
To get the top performing quarter:
SELECT TOP 1
Qtr,
SUM ( [Revenue] ) AS QtrRev
FROM #Revenue...
Returns
+-----+----------+
| Qtr | QtrRev |
+-----+----------+
| 2 | 12671.00 |
+-----+----------+
Ideally, you would add a Qtr column that stores the quarter the revenue belongs to, or at the very least change your Month column to a tinyint and store the numeric value over a string representation of the month.

Mysql: Fill column with consecutive numbers of days in a month

I have this table: "sales"
+-------------+---------+
| date | total |
+-------------+---------+
| 2018-12-04 | 269.10 |
| 2018-12-05 | 29.00 |
| 2018-12-06 | 107.10 |
| 2018-12-06 | 34.00 |
| 2018-12-08 | 69.50 |
| 2018-12-08 | 223.00 |
| 2018-12-08 | 68.00 |
| 2018-12-09 | 99.00 |
| 2018-12-10 | 59.50 |
| ... | ... |
+-------------+---------+
I'm trying this query
SELECT DAY(date) AS Days,
SUM(CASE WHEN MONTH(date) = 12 THEN total ELSE NULL END) AS December
FROM sales WHERE YEAR(date) = 2018 GROUP BY date
And I get
+-------+----------+
| Days | December |
+-------+----------+
| 4 | 269.10 |
| 5 | 29.00 |
| 6 | 141.10 |
| 8 | 360.50 |
| 9 | 99.00 |
| 10 | 59.50 |
| ... | ... |
+-------+----------+
But I want consecutive days like this:
+-------+----------+
| Days | December |
+-------+----------+
| 1 | NULL |
| 2 | NULL |
| 3 | NULL |
| 4 | 269.10 |
| 5 | 29.00 |
| 6 | 141.10 |
| 7 | NULL |
| 8 | 360.50 |
| 9 | 99.00 |
| 10 | 59.50 |
| ... | ... |
| 31 | 123.00 |
+-------+----------+
Can you help me plss..
PS: I have several months and years in "date" column from "sales" table.
This recursive CTE generates a list of dates corresponding to the month and year specified in the doi CTE, and then LEFT JOINs that to the sales table to get the sales for that month. It will work for any month/year, just change the values in the doi CTE, and the title of the SUM column (currently December) to suit.
WITH RECURSIVE doi AS (
SELECT 12 AS month,
2018 AS year
),
cte AS (
SELECT DATE(CONCAT_WS('-', year, month, 1)) AS date
FROM doi
UNION ALL
SELECT date + INTERVAL 1 DAY
FROM cte
WHERE date < LAST_DAY(date)
)
SELECT DAY(cte.date) AS Days,
ROUND(SUM(s.total),2) AS December
FROM cte
LEFT JOIN sales s ON s.date = cte.date
GROUP BY cte.date
ORDER BY cte.date
Output is too long to show here but can be seen at this demo on dbfiddle
Update
To expand this query to cover an entire year requires changing the approach slightly in terms of generating an entire year's worth of dates, and then using conditional aggregation to get the sums for each day of each month:
WITH RECURSIVE doi AS (
SELECT 2018 AS year
),
cte AS (
SELECT DATE(CONCAT_WS('-', year, 1, 1)) AS date
FROM doi
UNION ALL
SELECT date + INTERVAL 1 DAY
FROM cte
CROSS JOIN doi
WHERE date < DATE(CONCAT_WS('-', doi.year, 12, 31))
)
SELECT DAY(cte.date) AS Days,
ROUND(SUM(CASE WHEN MONTH(s.date) = 1 THEN s.total END),2) AS January,
ROUND(SUM(CASE WHEN MONTH(s.date) = 2 THEN s.total END),2) AS February,
ROUND(SUM(CASE WHEN MONTH(s.date) = 3 THEN s.total END),2) AS March,
ROUND(SUM(CASE WHEN MONTH(s.date) = 4 THEN s.total END),2) AS April,
ROUND(SUM(CASE WHEN MONTH(s.date) = 5 THEN s.total END),2) AS May,
ROUND(SUM(CASE WHEN MONTH(s.date) = 6 THEN s.total END),2) AS June,
ROUND(SUM(CASE WHEN MONTH(s.date) = 7 THEN s.total END),2) AS July,
ROUND(SUM(CASE WHEN MONTH(s.date) = 8 THEN s.total END),2) AS August,
ROUND(SUM(CASE WHEN MONTH(s.date) = 9 THEN s.total END),2) AS September,
ROUND(SUM(CASE WHEN MONTH(s.date) = 10 THEN s.total END),2) AS October,
ROUND(SUM(CASE WHEN MONTH(s.date) = 11 THEN s.total END),2) AS November,
ROUND(SUM(CASE WHEN MONTH(s.date) = 12 THEN s.total END),2) AS December
FROM cte
LEFT JOIN sales s ON s.date = cte.date
GROUP BY DAY(cte.date)
ORDER BY DAY(cte.date)
Demo on dbfiddle
generate your months using union and do right join
select t1.d as Days
, sum(iif(month(date) = 12, total, null) as December
from sales
right join (select 1 as d
union select 2 union select 3 union select 4 union select 5 union select 6
union select 7 union select 8 union select 9 union select 10 union select 11
.... ) as t1 on t1.d = day(date)
where year(date) = 2012
group by date
if you are using mysql v8.0, you can use recursive queries.
with recursive cte as(
select 1 as d
union all
select d + 1 from cte where d < day(last_day('2019-12-01'))
)
select coalesce(day(s.date), t1.d) as Days
, sum(iif(month(s.date) = 12, total, null) as December
from sales s
right join cte as t1 on t1.d = day(s.date)
where year(date) = 2012
group by coalesce(day(s.date), t1.d)

Merge two complex queries of SQL into single

I have 3 tables, one of the customer's, product_type_1 and product_type_2.
Customers
| id | name |
|----|-------|
| 1 | Alex |
| 2 | John |
| 3 | Ahmad |
| 4 | Sam |
product_type_1
| id | order_by | Date
|----|--------------|-------|
| 1 |------ 1 ---- | 2019-03-01
| 2 |------ 2 ----| 2019-03-02
| 3 |------ 2 ----| 2019-03-03
| 4 |------ 3 ----| 2019-03-04
product_type_2
| id | order_by | Date
|----|--------------|-------|
| 1 |------ 1 ---- | 2019-03-01
| 2 |------ 3 ----| 2019-03-02
| 3 |------ 3 ----| 2019-03-03
| 4 |------ 2 ----| 2019-03-04
The final output will be the sum of amount of both product type grouped by name of the customer of each month of a specific year. I have written query but it works for 1 product type at a time. But I want sum of both i.e:
Customer | Jan | Feb | Mar .... Total<br>
:------------------------------------------------------:
John ------ | 0 -- |--- 0 |--- 3 ...... 3
As John ordered total 3 products in 2019.
The query is
select c.name,
sum( month(o.order_date) = 1 and year(o.order_date)=2010) as Jan,
sum( month(o.order_date) = 2 and year(o.order_date)=2010) as Feb,
sum( month(o.order_date) = 3 and year(o.order_date)=2010) as Mar,
sum( month(o.order_date) = 4 and year(o.order_date)=2010) as Apr,
sum( month(o.order_date) = 5 and year(o.order_date)=2010) as May,
sum( month(o.order_date) = 6 and year(o.order_date)=2010) as Jun,
sum( month(o.order_date) = 7 and year(o.order_date)=2010) as Jul,
sum( month(o.order_date) = 8 and year(o.order_date)=2010) as Aug,
sum( month(o.order_date) = 9 and year(o.order_date)=2010) as Sep,
sum( month(o.order_date) = 10 and year(o.order_date)=2010) as Oct,
sum( month(o.order_date) = 11 and year(o.order_date)=2010) as Nov,
sum( month(o.order_date) = 12 and year(o.order_date)=2010) as December,
count(*) as total
from customers c join
(
select order_by as cID, order_price , order_date
from orders where year(order_date)=2010
) o
on o.cID = c.id and o.order_price > 0
group by c.name
order by total desc
Use union all and aggregation:
select c.id, c.name,
sum( month(o.order_date) = 1 and year(o.order_date)=2010) as Jan,
. . .
from customers c left join
((select order_by, date
from product_type_1
) union all
(select order_by, date
from product_type_2
)
) p12
on p12.order_by = c.id
group by c.id, c.name

MySql Transpose Row into Column and Column into Row [duplicate]

This question already has answers here:
How can I return pivot table output in MySQL?
(10 answers)
Closed 9 years ago.
i have problem with transposing row to column and column to row.
I can do that if it just transpose row to column or column to row.
This my table with data
UNIT|JAN|FEB|MAR|APR|MEI|JUN
CS-1|100|200|300|400|500|600
CS-2|111|222|333|444|555|666
CS-3|331|123|423|923|918|123
and I would like to get the following output
MONTH|CS-1|CS-2|CS-3
JAN |100 |111 |331
FEB |200 |222 |123
MAR |300 |333 |423
etc..
Anybody know how to do this? Thanks very much!
You can do it this way
SELECT month,
MAX(CASE WHEN unit = 'CS-1' THEN value END) `CS-1`,
MAX(CASE WHEN unit = 'CS-2' THEN value END) `CS-2`,
MAX(CASE WHEN unit = 'CS-3' THEN value END) `CS-3`
FROM
(
SELECT unit, month,
CASE month
WHEN 'JAN' THEN jan
WHEN 'FEB' THEN feb
WHEN 'MAR' THEN mar
WHEN 'APR' THEN apr
WHEN 'MAY' THEN may
WHEN 'JUN' THEN jun
END value
FROM table1 t CROSS JOIN
(
SELECT 'JAN' month UNION ALL
SELECT 'FEB' UNION ALL
SELECT 'MAR' UNION ALL
SELECT 'APR' UNION ALL
SELECT 'MAY' UNION ALL
SELECT 'JUN'
) c
) q
GROUP BY month
ORDER BY FIELD(month, 'JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN')
Output:
| MONTH | CS-1 | CS-2 | CS-3 |
|-------|------|------|------|
| JAN | 100 | 111 | 331 |
| FEB | 200 | 222 | 123 |
| MAR | 300 | 333 | 423 |
| APR | 400 | 444 | 923 |
| MAY | 500 | 555 | 918 |
| JUN | 600 | 666 | 123 |
Here is SQLFiddle demo

Sum Column Value

I Have query result like this , Select Type,Jan,FEB From TableName :
+-----------+------+------+
| Type | JAN | FEB |
+-----------+------+------+
| MATIC | 137 | 128 |
| MOPED | 41 | 23 |
| MOPED PRM | 8 | 9 |
| SPORT | 55 | 62 |
+-----------+------+------+
4 rows in set (1.23 sec)
I want to add up the columns jan and columns feb, be like this
+-----------+------+------+------+
| Type | JAN | FEB | TOT |
+-----------+------+------+------+
| MATIC | 137 | 128 | 165 |
| MOPED | 41 | 23 | 64 |
| MOPED PRM | 8 | 9 | 17 |
| SPORT | 55 | 62 | 117 |
+-----------+------+------+------+
4 rows in set (1.23 sec)
is there a command such as
select type, jan, feb, sum (jan) + sum (feb) As TOT
From Table Name
This is my syntax
Select SubTbl2.jenis,
sum(If(Month = 1 and Year = 2013 ,Result,0)) as 'JAN',
sum(If(Month = 2 and Year = 2013,Result,0)) as 'FEB'
From (
select SubTbl1.jenis,month(SubTbl1.TglAmb) as Month,
year(SubTbl1.tglAmb) as Year,
count(SubTbl1.jenis) as Result
From (
select jual_leasing.TglAmb,jual_leasing.NoMsn,typemotor.jenis
,lokasi.lokasi3s
from jual_leasing
left join typeconvert
on jual_leasing.typeK = typeconvert.typesystem
left join typemotor
on typeconvert.typeconv = typemotor.type
left join lokasi
on jual_leasing.kodelok = lokasi.kodelokasi
where
lokasi.lokasi3S = 'YMS PURWODADI 3S'
group by jual_leasing.NoMsn)
as SubTbl1
group by SubTbl1.jenis,Month,Year )
as SubTbl2 group by SubTbl2.jenis;
The result is on Top , i try to add script on line 4 , with
JAN + FEB as TOT
but there is stil warning :
ERROR 1054 (42S22): Unknown column 'JAN' in 'field list'
Tq For advanced
To obtain tour desired output, simply do:
select type, jan, feb, jan + feb As TOT
from TableName
You do not need SUM, that is designed to add the values of different rows.
edit For your actual query, yes you can add two sums. Also, the following should work for you:
sum(If((Month = 1 or Month = 2) and Year = 2013 ,Result,0)) as 'TOT',
The MySQL documentation on arithmetic functions indicates that + is indeed the addition operator.
So, your query would be:
select type, jan, feb, jan + feb from table
Sum works over columns and not rows; you'd use this if you wanted the sum of both columns added together.
P.S. 137 + 128 = 265
I think you will find this question is getting down-voted because it is not really about programming - this is more of a general SQL syntax question. That being said, I think you should just be able to sum your values:
select type, jan, feb, jan + feb As TOT From Table Name
Just change the beginning of your query with this :
Select SubTbl2.jenis,
sum(If(Month = 1 and Year = 2013 ,Result,0)) as 'JAN',
sum(If(Month = 2 and Year = 2013,Result,0)) as 'FEB',
sum(If(Month = 1 and Year = 2013 ,Result,0)) +
sum(If(Month = 2 and Year = 2013,Result,0)) as 'TOT'
From (
Or
Select SubTbl2.jenis,
sum(If(Month = 1 and Year = 2013 ,Result,0)) as 'JAN',
sum(If(Month = 2 and Year = 2013,Result,0)) as 'FEB',
sum(If((Month = 1 or Month = 2) and Year = 2013,Result,0)) as 'TOT'
From (