Pivot table query in mysql - mysql

Is there a way to do a query in mysql with this scenario.
i have a table
group_name | cost_period | books_cost | others_cost
group_A | 1/01/2015 | 100 | 200
group_A | 1/02/2015 | 56 | 86
group_A | 1/01/2015 | 22 | 222
group_A | 1/03/2015 | 30 | 40
group_B | 1/02/2015 | 50 | 10
group_B | 1/02/2015 | 45 | 10
group_B | 1/01/2015 | 22 | 15
group_C | 1/02/2015 | 45 | 20
and i want it to have this format after the query
JAN-2015 FEB-2015 MAR_2015 total
group_A
sum of book cost 122 56 30 208
sum of others cost 422 86 40 548
group_B
sum of book cost 22 95 0 117
sum of others cost 15 20 0 45
group_C
sum of book cost 0 45 0 45
sum of others cost 0 20 0 20
is there a way this is possible by a query to avoid using a pivot tool once data is gathered? since jasper's crosstabs are not that flexible
thanks

Related

How to merge two tables using single query

I have three tables named receipt, receiptdet. The receipt table store record of the receipt information while the receiptdet stores the fees details in that receipt.
Table receipt:
receiptno | payor | amount
66 | 333 | 1600
67 | 332 | 1500
68 | 215 | 300
Table receiptdet:
receiptno | fee | amount
66 | 21 | 50
66 | 33 | 50
66 | 55 | 1500
67 | 55 | 1500
68 | 12 | 100
68 | 44 | 100
68 | 22 | 100
Table fees:
Id | code | inassess
12 | Xbre | 0
21 | Drop | 0
22 | Stest | 0
33 | Perm | 0
44 | Afee | 0
55 | TFee | 1
I want a query that will display records based on the selected field if "INASSESS" field is either 0 or 1 AND SUM THE TOTAL AMOUNT ON RECEIPDET table.
DESIRED OUTPUT
receiptno | payor | SUM(receiptdet.amount) | inassess
66 | 333 | 1500 | 1
67 | 332 | 1500 | 1
OR
receiptno | payor | SUM(receiptdet.amount) | inassess
66 | 333 | 100 | 0
68 | 215 | 300 | 0
so far i have to working separate query for both table. and i want to make it as one single query if someone can help me i will greatly appreciate it. thanks in advance
SELECT
receipt.receiptno,
receipt.amount
FROM
receipt ORDER
BY LENGTH(receipt.receiptno), receipt.receiptno
SELECT
Sum(receiptdet.amount),
receiptdet.student,
feetype.inassess,
receiptdet.receiptno
FROM
receiptdet
Left Join fees ON receiptdet.fee = fees.id
Left Join feetype ON fees.feetype = feetype.id
WHERE
feetype.inassess = '0' AND
receiptdet.receiptno = '66'
You can use JOINs to put all the tables together by their linking columns, then use GROUP BY to group the data according to receiptno and inassess. One query will give you all the data you require:
SELECT r.receiptno, r.payor, SUM(rd.amount) AS fees, f.inassess
FROM receipt r
LEFT JOIN receiptdet rd ON rd.receiptno = r.receiptno
JOIN fees f ON f.id = rd.fee
GROUP BY f.inassess, r.receiptno
For your sample data, this gives:
receiptno payor fees inassess
66 333 100 0
68 215 300 0
66 333 1500 1
67 332 1500 1
SQLFiddle

Count call answered within certain ranges 0 to 10 sec, group by count

I need to count call answered within certain ranges 0 to 10 sec, 0 to 20 sec, etc. The count will increase while the delta will be the different count between the current and the next. The % will be the current count / the final count total.
Here is the sqlfiddle that you can use with data for testing: http://sqlfiddle.com/#!9/803d2/2
Sample table of callsdetails:
+-----+----------------+----------+----------+---------------+
| id | callid | callerno | duration | status |
+-----+----------------+----------+----------+---------------+
| 634 | 1479097551.228 | 1000 | 2 | complete |
| 635 | 1479102518.248 | 1000 | 12 | complete |
+-----+----------------+----------+----------+---------------+
Expected Result:
+------------------------+----------+----------+----------+
| Ranges | Count | Delta | % |
+------------------------+----------+----------+----------+
| Between 0 to 10 secs | 44 | +44 | 84.62 % |
| Between 0 to 20 secs | 48 | +4 | 92.31 % |
| Between 0 to 30 secs | 50 | +2 | 96.15 % |
| Between 0 to 40 secs | 51 | +1 | 98.08 % |
| Between 0 to 50 secs | 51 | +0 | 98.08 % |
| Between 0 to 60 secs | 51 | +0 | 98.08 % |
| Between 0 to 70 secs | 51 | +0 | 98.08 % |
| Between 0 to 80 secs | 52 | +1 | 100.00 % |
| Between 0 to 90 secs | 52 | +0 | 100.00 % |
| Between 0 to 100+ secs | 52 | +0 | 100.00 % |
+------------------------+----------+----------+----------+
Total 52
What I am able to create now is below query, if you can help to provide better solution, please advice. The problem that I face now is (Priority) I am not able to get the count and (secondary) the final count total (52) for the %, now I manually put in the final count total (52). Please help.
SELECT Ranges,Delta,ROUND(Delta/52*100,2) AS '%'
FROM
(
SELECT
(
IF(duration<=10,'10',IF(duration<=20,'20',IF(duration<=30,'30',
IF(duration<=40,'40',IF(duration<=50,'50',
IF(duration<=60,'60',IF(duration<=70,'70',IF(duration<=80,
'80',IF(duration<=90,'90','100+'))))))))))
AS Ranges,COUNT(duration) AS Delta
FROM callsdetails
GROUP BY Ranges
) a
GROUP BY Ranges;
Current Result:
+--------+-------+-------+
| Ranges | Delta | % |
+--------+-------+-------+
| 10 | 44 | 84.62 |
| 20 | 4 | 7.69 |
| 30 | 2 | 3.85 |
| 40 | 1 | 1.92 |
| 80 | 1 | 1.92 |
+--------+-------+-------+
If i understood your problem then you just want ROLLUP grouping funtion in mysql
your query
SELECT Ranges,Delta,ROUND(Delta/52*100,2) AS '%'
FROM
(
SELECT
(
IF(duration<=10,'10',IF(duration<=20,'20',IF(duration<=30,'30',
IF(duration<=40,'40',IF(duration<=50,'50',
IF(duration<=60,'60',IF(duration<=70,'70',IF(duration<=80,
'80',IF(duration<=90,'90','100+'))))))))))
AS Ranges,COUNT(duration) AS Delta
FROM callsdetails
GROUP BY Ranges
) a
GROUP BY Ranges WITH ROLLUP;
FOR MORE REFERENCE

MYSQL/Query: How to make table rows into column

I have 3 tables tbl_contestant , tbl_criteria and tbl_judges. And then i have 1 more table combined this 3 table as my result, tbl_score.
tbl_criteria
------------------------
crit_id | criteria_name
16 | sports
tbl_judges
------------------------
judge_id | judge_name
61 | first
62 | second
63 | third
tbl_cotestant
--------------------------------------
con_id | contestant_number | contestant_name |
1 | 1 | john |
2 | 2 | sy |
3 | 3 | Nah |
tbl_score
--------------------------------------------------
score_id | crit_id | judge_id | contestant_number | score
1 | 16 | 61 | 1 | 25
2 | 16 | 61 | 2 | 25
3 | 16 | 61 | 3 | 25
4 | 16 | 62 | 1 | 25
5 | 16 | 62 | 2 | 73
6 | 16 | 62 | 3 | 59
7 | 16 | 63 | 1 | 70
8 | 16 | 63 | 2 | 80
9 | 16 | 63 | 3 | 70
How can i achieve this output, judge_id row turns into column based on crit_id
contestant_number | contestant_name | 16_judge_61 | 16_judge_62 | 16_judge_63 | total
1 | john | 25 | 25 | 70 |
2 | sy | 25 | 73 | 80 |
3 | Nah | 25 | 59 | 70 |
Please correct my query
SELECT DISTINCT(c.contestant_number) , contestant_name , j1.sports as
16_judge_61, j2.sports as 16_judge_62, j3.sports as 16_judge_63 from
tbl_criteria , tbl_score, tbl_contestant c
LEFT JOIN tbl_ // <-- i have no idea how start from here joining those 4 tables together
You could use CASE WHEN to solve this.
SELECT
s.contestant_number,
c.contestant_name,
SUM(CASE WHEN s.crit_id='16' AND s.judge_id='61' THEN s.score END) as 16_judge_61,
SUM(CASE WHEN s.crit_id='16' AND s.judge_id='62' THEN s.score END) as 16_judge_62,
SUM(CASE WHEN s.crit_id='16' AND s.judge_id='63' THEN s.score END) as 16_judge_63,
SUM(s.score) as Total
FROM tbl_score s
INNER JOIN tbl_contestant c ON s.contestant_number = c.contestant_number
GROUP BY s.contestant_number
see SQL Fiddle http://sqlfiddle.com/#!9/9efa5/1

SQL sub queries - one alias column

course_completions
+-----------------------------------------------+
| id coursemodid userid state timemodified |
+-----------------------------------------------+
| 370 23 2 1 1433582890 |
| 329 24 89 1 1427771915 |
| 333 30 39 1 1428309816 |
| 332 32 39 1 1428303307 |
| 327 33 40 1 1427689703 |
| 328 34 89 1 1427710711 |
| 303 35 41 1 1410258482 |
| 358 36 99 1 1432020067 |
| 365 25 2 1 1433142455 |
| 304 26 69 1 1410717866 |
| 353 37 95 1 1430387005 |
| 416 38 2 1 1438972465 |
| 300 27 70 1 1409824001 |
| 302 29 74 1 1412055704 |
| 297 30 2 1 1409582123 |
| 301 133 41 1 1410255923 |
| 336 133 91 1 1428398435 |
| 364 133 40 1 1433142348 |
| 312 133 85 1 1425863621 |
+-----------------------------------------------+
course_modules
+------------------+
| id course |
+------------------+
| 23 6 |
| 24 6 |
| 25 6 |
| 26 6 |
| 27 6 |
| 28 6 |
| 29 8 |
| 30 8 |
| 31 8 |
| 32 8 |
| 33 8 |
| 34 5 |
| 35 5 |
| 36 5 |
| 37 5 |
| 38 5 |
| 39 9 |
| 40 9 |
| 41 9 |
+------------------+
course_mod_settings
+--------------------------------------+
|id course modinstance |
+--------------------------------------+
| 27 8 30 |
| 28 8 31 |
| 29 8 32 |
| 30 8 33 |
| 31 6 23 |
| 32 6 24 |
| 33 6 25 |
| 34 6 26 |
| 35 6 27 |
| 36 6 28 |
| 37 9 39 |
| 38 9 40 |
| 39 9 41 |
+--------------------------------------+
I was trying about to frame two sub queries in one SQL statement like I want the count of 'criteria mod settings' table values in one column and count of 'course_completions' table values in one column for a particular user along with course.
There shouldn't be relation between count(cms.id) and count(cc.id) except course id, because count(cms.id) is the count of user modules and count(cc.id) is the settings count set by default.
OUTPUT:
COURSE USERID count(cms.id) count(cc.id)
6 89 3 6
6 39 7 6
6 40 5 6
8 69 3 4
8 2 0 4
8 95 4 4
COURSE : getting courseid
USERID : getting userid
count(cms.id) : getting the count of user completed modules.
count(cc.id) : getting the count of settings (ex: For course 6, settings count has 6 and for course 4, settings count has 3.
SELECT cm.course
,cc.userid
,count(cc.coursemodid) AS usermodules
,(
SELECT count(ccc.id)
FROM course_mod_settings cms
INNER JOIN course_modules cm ON cms.course = cm.course
) AS modsettings
FROM course_completions cc
INNER JOIN course_modules cm ON cc.coursemodid = cm.id
WHERE cc.STATE = 1
GROUP BY cm.cours
,cc.userid
I have read your comment above.
Have you tried something like this?
I didn't test the query, it's just a thought.
I might be wrong.
SELECT cms.course AS COURSE, cc.userid AS USERID, COUNT(cms.id), COUNT(cc.id) FROM
course_completions AS cc
INNER JOIN course_modules AS cm ON cc.coursemodid = cm.id
INNER JOIN course_mod_settings AS cms cm.course = cms.course
WHERE cc.state = 1
GROUP BY cm.course, cc.userid

Dynamic Cross Tab in MySQL

I have the following table with the following data
Year | Age Group | Male | Female
2000 | 0 - 25 | 50 | 100
2000 | 26 above | 40 | 75
2001 | 0 - 25 | 150 | 86
2001 | 26 above | 65 | 83
I would like to create a cross tab in the following format
| Male | Female
2000 | 90 | 175
0 - 25 | 50 | 100
26 above | 40 | 75
2001 | 215 | 169
0 - 25 | 150 | 86
26 above | 65 | 83
I will be very grateful for your assistance.
SQLFiddle example:
select * from
(
select year,ageGroup,male,female from t
union all
select year,'' ageGroup,sum(male) male,sum(female) female
from t group by year
) st
order by year,agegroup