How to combine these queries that group by the same field? - mysql

I have the following three queries
SELECT COUNT(*) as cached_type_a, DATE(datetime) as datetime
FROM requests
WHERE cached = 'a'
GROUP BY DAY(datetime);
SELECT COUNT(*) as cached_type_b, DATE(datetime) as datetime
FROM requests
WHERE cached = 'b'
GROUP BY DAY(datetime);
SELECT COUNT(*) as cached_type_c, DATE(datetime) as datetime
FROM requests
WHERE cached = 'c'
GROUP BY DAY(datetime);
Is it possible to combine them into a single query with 4 columns
cached_type_a, cached_type_b, cached_type_c, datetime?

If you have only three possible values of cache, you can use this,
SELECT DATE(datetime) as datetime,
SUM(CASE WHEN cached = 'a' THEN 1 ELSE 0 END) cached_a,
SUM(CASE WHEN cached = 'b' THEN 1 ELSE 0 END) cached_b,
SUM(CASE WHEN cached = 'c' THEN 1 ELSE 0 END) cached_c
FROM requests
GROUP BY DAY(datetime)
otherwise, if you have multiple number of cache, you can use Prepared Statement
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN cached = ''',
cached,
''' then 1 ELSE 0 end) AS ',
CONCAT('cached_',cached)
)
) INTO #sql
FROM requests;
SET #sql = CONCAT('SELECT DATE(datetime) as datetime, ', #sql, '
FROM requests
GROUP BY DAY(datetime)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SELECT COUNT(a.datetime) as cached_type_a,
COUNT(b.datetime) as cached_type_b,
COUNT(c.datetime) as cached_type_c,
DATE(a.datetime) as datetime
FROM requests a,
requests b,
requests c,
WHERE a.cached = 'a'
and b.cached = 'b'
and c.cached = 'c'
GROUP BY DAY(a.datetime), DAY(b.datetime), DAY(c.datetime);

Related

How to you create a table of counts between two columns without having to list every column name? (SQL)

For example, this is the part of my data set I'm interested in:
EventID
Action
Actor
EventID1
ActionB
ActorX
EventID2
ActionB
ActorZ
EventID1
ActionA
ActorY
EventID2
ActionC
ActorZ
EventID3
ActionA
ActorX
EventID3
ActionB
ActorZ
EventID2
ActionB
ActorZ
EventID2
ActionA
ActorY
I Want:
ActorX
ActorY
ActorZ
ActionA
1
2
0
ActionB
1
0
3
ActionC
0
0
1
The problem is I have LOTS of actors and actions--so I need a way of doing this without listing each one.
You create this as pairs within a row, rather than as a matrix:
select t1.action, t1.actor, t2.actor, count(*)
from t t1 join
t t2
on t1.action = t2.action
group by t1.action, t1.actor, t2.actor;
Pivoting the data into a matrix is best handled at the application layer. You can construct dynamic SQL to do this as well. Or you could construct a JSON data structure to contain the elements.
Try using Prepared statement.
Set #sql & #sql2 variable as NULL; in case the variable being used before, we're resetting it to NULL.
SET #sql = NULL;
SET #sql2 = NULL;
Set #sql variable with list of actor adding SUM() as method of counting and CASE expression to match the actor value:
SELECT GROUP_CONCAT(
CONCAT(' SUM(CASE WHEN Actor = "', Actor,'" THEN 1 ELSE 0 END) AS ',Actor))
INTO #sql
FROM ( SELECT DISTINCT Actor FROM mytable ORDER BY Actor) AS b;
At this point, when you run SELECT #sql;, you'll get this result:
SUM(CASE WHEN Actor = "ActorX" THEN 1 ELSE 0 END) AS ActorX,
SUM(CASE WHEN Actor = "ActorY" THEN 1 ELSE 0 END) AS ActorY,
SUM(CASE WHEN Actor = "ActorZ" THEN 1 ELSE 0 END) AS ActorZ
Set #sql2 variable with the final query combination of SELECT ... FROM table with the dynamically generated column that was set in #sql variable.
SET #sql2=CONCAT('SELECT Action,',#sql,' FROM mytable GROUP BY Action ORDER BY Action');
At this point, when you run SELECT #sql2;, you'll get this result:
SELECT Action,
SUM(CASE WHEN Actor = "ActorX" THEN 1 ELSE 0 END) AS ActorX,
SUM(CASE WHEN Actor = "ActorY" THEN 1 ELSE 0 END) AS ActorY,
SUM(CASE WHEN Actor = "ActorZ" THEN 1 ELSE 0 END) AS ActorZ
FROM mytable
GROUP BY Action
ORDER BY Action
Prepare, execute then deallocate the statement with the following command;
PREPARE stmt FROM #sql2;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Demo fiddle

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 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;

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

how to display data in mysql like pivot in excel

I have query like this:
SELECT DATE,REGION,COUNT(*)
FROM ALL_ID_DATA
WHERE DATE in (SUBDATE(CURDATE(),1),SUBDATE(CURDATE(),2),SUBDATE(CURDATE(),8))
AND DIRECTION='inbound'
AND REASON_1 = 'complaint'
GROUP BY REGION,DATE DESC
and the result is
What is the right query to display like this capture below
Could somebody help me?
This type of query is known as a PIVOT. Unfortunately, MySQL doesn't have a PIVOT function, so you will need to replicate the function using a CASE statement and an aggregate function.
If you know the number of columns to transform, then you can hard-code the values:
select region,
SUM(CASE WHEN date = '2012-09-24' THEN 1 END) as `2012-09-24`,
SUM(CASE WHEN date = '2012-09-30' THEN 1 END) as `2012-09-30`,
SUM(CASE WHEN date = '2012-10-01' THEN 1 END) as `2012-10-01`
from ALL_ID_DATA
group by region;
select region,
COUNT(CASE WHEN date = '2012-09-24' THEN 1 ELSE null END) as `2012-09-24`,
COUNT(CASE WHEN date = '2012-09-30' THEN 1 ELSE null END) as `2012-09-30`,
COUNT(CASE WHEN date = '2012-10-01' THEN 1 ELSE null END) as `2012-10-01`
from ALL_ID_DATA
group by region;
See SQL Fiddle with Demo.
Then adding this to your existing query, it would be:
SELECT REGION,
SUM(CASE WHEN date = '2012-09-24' THEN 1 END) as `2012-09-24`,
SUM(CASE WHEN date = '2012-09-30' THEN 1 END) as `2012-09-30`,
SUM(CASE WHEN date = '2012-10-01' THEN 1 END) as `2012-10-01`
FROM ALL_ID_DATA
WHERE DATE in (SUBDATE(CURDATE(),1),SUBDATE(CURDATE(),2),SUBDATE(CURDATE(),8))
AND DIRECTION='inbound'
AND REASON_1 = 'complaint'
GROUP BY REGION
OR
SELECT REGION,
COUNT(CASE WHEN date = '2012-09-24' THEN 1 ELSE null END) as `2012-09-24`,
COUNT(CASE WHEN date = '2012-09-30' THEN 1 ELSE null END) as `2012-09-30`,
COUNT(CASE WHEN date = '2012-10-01' THEN 1 ELSE null END) as `2012-10-01`
FROM ALL_ID_DATA
WHERE DATE in (SUBDATE(CURDATE(),1),SUBDATE(CURDATE(),2),SUBDATE(CURDATE(),8))
AND DIRECTION='inbound'
AND REASON_1 = 'complaint'
GROUP BY REGION
Now if you have an unknown number of dates to transform into columns, then you can use prepared statements and your query would be similar to this (See SQL Fiddle with Demo):
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(case when date = ''',
date,
''' then 1 else 0 end) AS ''',
Date(date), ''''
)
) INTO #sql
FROM ALL_ID_DATA;
select #sql;
SET #sql = CONCAT('SELECT region, ', #sql, '
FROM ALL_ID_DATA
GROUP BY region');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Then placing your original query in the prepared statement the final query would be:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(case when date = ''',
date,
''' then 1 else 0 end) AS ''',
Date(date), ''''
)
) INTO #sql
FROM ALL_ID_DATA;
select #sql;
SET #sql = CONCAT('SELECT region, ', #sql, '
FROM ALL_ID_DATA
WHERE DATE in (SUBDATE(CURDATE(),1),SUBDATE(CURDATE(),2),SUBDATE(CURDATE(),8))
AND DIRECTION=''inbound''
AND REASON_1 = ''complaint''');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I think you are looking for this :
http://www.artfulsoftware.com/infotree/queries.php#78