MySQL SELECT and GROUPING - mysql

I am new to SQL (mySQL) and I am trying to create a query that will populate a google chart specifically
The result should look something like this:
['group_name', 'Open_tickets_count', 'closed_tickets_count'],
['Team A', 10, 400],
['Team B', 30, 460],
['Team C', 66, 1120],
['Team D', 5, 540]
I have a tickets table that includes the following fields: id ticket_status group_name.
A few things:
In this example I only have two statuses, but the number of
statuses is actually variable
The number of teams is also variable
the actual group_names and tickets_statuses are ids to other
tables in my real table. (but I can figure out how to substitute)
I have tried everything my imagination and limited knowledge allows and got not even near to achieve this. Any help or pointers would be highly appreciated.
Thank you.
[Adding sample table structures (only relevant fields)]
Table: tickets
'id', 'int(10)'
'ticket_status_id', 'int(10)'
'ticket_group_id', 'int(10)'
Table: status
'id', 'int(10)'
'name', 'varchar(250)'
Table: groups
'id', 'int(10)'
'name', 'varchar(250)'

In order to achieve your goal you need to use conditional SUM() with GROUP BY and dynamic SQL (PREPARE, EXECUTE).
Your base script might look like this
SET #sql = '';
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN t.ticket_status = ''',
id,
''' THEN 1 ELSE 0 END) `',
name, '`'
)
) INTO #sql
FROM
status;
SET #sql = CONCAT
('SELECT g.name, ', #sql, '
FROM tickets t JOIN status s
ON t.ticket_status = s.id JOIN groups g
ON t.ticket_group_id = g.id
GROUP BY t.ticket_group_id, g.name'
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Here is SQLFiddle demo.

Lets go with your assumptions.
You can try something like
SELECT group_name,
SUM(CASE WHEN ts.status = 'OPEN' THEN 1 ELSE 0 END) Open_tickets_count
SUM(CASE WHEN ts.status = 'CLOSED' THEN 1 ELSE 0 END) closed_tickets_count
FROM tickets t INNER JOIN
ticket_statusses ts ON t.ticket_status = ts.id
GROUP BY group_name
You would have to add new columns for different statusses.

Related

How to aggregate values inside a column in SQL?

I could not solve this question, any help?
Batsman_detail table has the columns ,
[Opposition (varchar), runs(int), dismissal(varchar), venue(varchar)]:
opposition column has may countries in it.
runs column has the amount of runs scored by the batsman in that match.
dimissal column has any of the following values caught/bowled/run out/not out.
venue column has the stadium name where the match is held.
Now you should write a query such that the output table must have that number of times the batsman had gone out in a type of dismissal against the countries Pakistan,Australia and Srilanka (Original table contains many countries.),
Example output format :
opposition caught bowled runout notout
Pakistan 3 5 7 9
Australia 0 4 4 1
Sri Lanka 4 2 3 4
You seem to want conditional aggregation:
select opposition,
sum(case when dismissal = 'caught' then runs else 0 end) caught,
sum(case when dismissal = 'bowled' then runs else 0 end) bowled,
sum(case when dismissal = 'run out' then runs else 0 end) run_out,
sum(case when dismissal = 'not out' then runs else 0 end) not_out
from batsman
group by opposition
This sums the runs for each value of dismissal. If you just want to count the occurences, then:
select opposition,
sum(dismissal = 'caught') caught,
sum(dismissal = 'bowled') bowled,
sum(dismissal = 'run out') run_out,
sum(dismissal = 'not out') not_out
from batsman
group by opposition
You can distinctly select all dismissal cases and then pivot dynamically as
SET #sql = NULL;
SELECT GROUP_CONCAT(
CONCAT(
'SUM(CASE WHEN dismissal =''', dismissal, ''' THEN runs ELSE 0 END ) AS ',
dismissal
)
)
INTO #sql
FROM ( SELECT DISTINCT dismissal
FROM Batsman_detail
) b;
SET #sql = CONCAT('SELECT opposition,',#sql,
' FROM Batsman_detail
GROUP BY opposition');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Demo

MySQL select non null columns on pivoted table

I'm still having some troubles to understand pivoted tables, but I managed to do this working query:
select region,
sum(case when rescheduleCause = 'CLOSED' then round(reschedulePercentage,2) end) as 'CLOSED',
sum(case when rescheduleCause = 'RESHUFFLE' then round(reschedulePercentage,2) end) as 'RESHUFFLE',
sum(case when rescheduleCause = 'NEW PRIORITY' then round(reschedulePercentage,2) end) as 'NEW PRIORITY'
from fancy_table
group by region
I'm getting the following result which calculations are correct:
region | CLOSED | RESHUFFLE | NEW PRIORITY
___________________________________________
RegionA | 23.08 | NULL | 38.46
RegiobB | 23.08 | NULL | 7.69
My problem in that RESHUFFLE column full of NULL values. My desired result set would look like this:
region | CLOSED | NEW PRIORITY
___________________________________________
RegionA | 23.08 | 38.46
RegiobB | 23.08 | 7.69
I know this can be achieved if I modify this query into a stored procedure using a dynamic sql, but the columns I need are as limitated as these ones, so I think it's not really that necessary. I've tried:
ifnull(sum(case when rescheduleCause = 'RESHUFFLE' then round(reschedulePercentage,2) end),0) as 'RESHUFFLE',
where `RESHUFFLE` is not null
where 'RESHUFFLE' is not null
having `RESHUFFLE` is not null
I'm out of ideas.
When you are querying in SQL you need to know the number of columns ahead of time, you can't just exclude columns on the fly. If you are going to have an unknown number of columns, then you'll need to use dynamic SQL to first create a sql string that will be executed.
In MySQL this can be done using prepared statements. This will first query your table to only return the rescheduleCause values that you actually have. These values are concatenated together into a sql string, then you'll use this string to create your final query to be executed:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(case when rescheduleCause = ''',
rescheduleCause,
''' then round(reschedulePercentage,2) end) AS ',
replace(rescheduleCause, ' ', '')
)
) INTO #sql
from fancy_table;
SET #sql = CONCAT('SELECT region, ', #sql, '
from fancy_table
group by region');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
See SQL Fiddle with Demo

MySQL sum results into a table grid format

I have the following SQL code:
select distinct members_main.membership_type,
payment_method,sum(amount_paid)
from members_main, members_payments
where members_main.contact_id=members_payments.contact_id
group by members_main.membership_type,payment_method
That returns the following:
I want to be able to return the results in the following table grid format:
Does anyone know if or how I can do this within MySQL?
Thanks,
John
Depending on data complexity either go with bluefeet's way or if the payment_method amount is dynamic then it sounds like you need a pivot table. Try looking at this.
MySQL does not have a pivot function but you can use a CASE expression and an aggregate function to turn the rows into columns:
select m.membership_type,
sum(case when p.payment_method = 'Cash' then amount_paid else 0 end) Cash,
sum(case when p.payment_method = 'Credit Card' then amount_paid else 0 end) CreditCard,
sum(case when p.payment_method = 'Paypal' then amount_paid else 0 end) Paypal
from members_main m
inner join members_payments p
on m.contact_id=p.contact_id
group by m.membership_type;
If you are going to have an unknown number of payment_method's, then you will want to look at using a prepared statement to generate dynamic SQL:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(CASE WHEN p.payment_method = ',
payment_method,
' THEN amount_paid else 0 END) AS `',
payment_method, '`'
)
) INTO #sql
FROM members_payments ;
SET #sql
= CONCAT('SELECT m.membership_type, ', #sql, '
from members_main m
inner join members_payments p
on m.contact_id=p.contact_id
group by m.membership_type');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

MYSQL: count column if something if another column is equal to something else

I have the following table:
----------------------------------------------
|ID|Vote_Item_ID|User_ID|Country_code| Vote|
|01| 105102151|user1 | CA| like|
|02| 105102151|user2 | CA|dislike|
|03| 105102151|user3 | UK|dislike|
|04| 105102151|user4 | UK| like|
|05| 105102151|user5 | UK| like|
----------------------------------------------
What I need to do is create an SQL statement that creates an array which totals the likes and dislikes for each country...The script I am using this with has 175 countries, so would this be an inefficient way to about it?
I'm not sure how to go about writing the Select statement, since I want the script to be reusable for many different "vote_item_id"s
I am using PDO with a MYSQL database by the way.
Thanks
SELECT Country_Code,
SUM(CASE WHEN vote = 'like' THEN 1 ELSE 0 END) `like`,
SUM(CASE WHEN vote = 'dislike' THEN 1 ELSE 0 END) dislike
FROM tableName
GROUP BY Country_Code
SQLFiddle Demo
or if you want PreparedStatement (both give the same results)
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN vote = ''',
Vote,
''' then 1 Else 0 end) AS `',
Vote, '`'
)
) INTO #sql
FROM TableName;
SET #sql = CONCAT('SELECT Country_Code, ', #sql, '
FROM tableName
GROUP BY Country_Code');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SQLFiddle Demo
If you had shown your expected output, that would have been great.
Following sample is simple. So let us know what you really need beyond this. Would be happy to pitch in. :)
REFERENCE : SQLFIDDLE
CODE:
SELECT t.country_code,
sum(CASE WHEN t.vote = 'like'
THEN 1 ELSE 0 END) AS LIKES,
sum(CASE WHEN t.vote = 'dislike'
THEN 1 ELSE 0 END) AS DISLIKE
FROM tbl t
GROUP BY t.country_code
;
RESULTS:
COUNTRY_CODE LIKES DISLIKE
CA 1 1
UK 2 1

How to get the output in mysql the way i need is give below

i have one table with a single column having three values a,b and c.
Current snapshot of the table is
Table name:- tblTest
Values
tblColumn
a
a
a
b
b
b
b
c
c
i need to get the output exactly as
A B C
3 4 2
select sum(tblColumn = 'a') as A,
sum(tblColumn = 'b') as B,
sum(tblColumn = 'b') as C
from tblTest
SQL Fiddle Example
SELECT SUM(CASE WHEN colName = 'a' THEN 1 ELSE 0 END) as A,
SUM(CASE WHEN colName = 'b' THEN 1 ELSE 0 END) as B,
SUM(CASE WHEN colName = 'c' THEN 1 ELSE 0 END) as C
FROM tableName
another technique is by using PreparedStatement, this is very good if you have multiple unknown number group of values, eg, a,b,c,d,e,f,g,h,...
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(IF(tblColumn = ''',
tblColumn,
''', 1, 0)) AS ',
tblColumn
)
) INTO #sql
FROM
Table1;
SET #sql = CONCAT('SELECT ', #sql, ' FROM Table1');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SQLFiddle Demo
Try this
select tblColumn, Count(*) from tblTest group by tblColumn