Multiple counts and a group by - mysql

I have a database (MySQL 5.5) similar to this:
ID Name Page Visited Date
1 Tim Page A 11-2-2000
1 Tim Page B 11-3-2000
1 Tim Page B 11-3-2000
2 Jeff Page C 11-5-2000
2 Jeff Page A 11-11-2000
I want to build a query (trying to at the moment), where the results would be similar to this:
ID Name Page A Visits Page B Visits Page C Visits
1 Tim 1 2 0
I assume that I need to run the following query against a subset (my question is how do I do this with essentially 3 counts)?:
SELECT * From database.mytable GROUP BY ID HAVING COUNT(*) >=1

SELECT ID, Name,
SUM(CASE WHEN `Page Visited` = 'Page A' THEN 1 ELSE 0 END) `Page A Visit`,
SUM(CASE WHEN `Page Visited` = 'Page B' THEN 1 ELSE 0 END) `Page B Visit`,
SUM(CASE WHEN `Page Visited` = 'Page C' THEN 1 ELSE 0 END) `Page C Visit`
FROM tableName
GROUP BY ID, Name
SQLFiddle Demo
if you have unknown number of page, you can also PreparedStatement
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN `Page Visited` =''',
`Page Visited`,
''' then 1 ELSE 0 end) AS ',
CONCAT('`',`Page Visited`, ' Visits`')
)
) INTO #sql
FROM TableName;
SET #sql = CONCAT('SELECT ID, Name, ', #sql, '
FROM tableName
GROUP BY ID, Name');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SQLFiddle Demo

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

Complex query from MySQL with GROUP_CONCAT

I'm looking for a way to SELECT this result:
id_item name1 name2 name3
1 value10 value20 value30
2 - value40 -
3 value50 value60 -
From this DB table (here's custom fields to each id_item):
id_item Name Value
1 name1 value10
1 name2 value20
1 name3 value30
2 name2 value40
3 name1 value50
3 name2 value60
Can't solve it. Is there a way?
You can get your new result with this query:
SELECT
id_item,
MAX(CASE WHEN Name = 'name1' THEN value ELSE '-' END) name1,
MAX(CASE WHEN Name = 'name2' THEN value ELSE '-' END) name2,
MAX(CASE WHEN Name = 'name3' THEN value ELSE '-' END) name3
FROM
your_table
GROUP BY
id_item;
Demo
I adapted this great answer of bluefeet to generate this query dynamically:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
'MAX(CASE WHEN e.Name = ''',
e.Name,
''' THEN value ELSE ''-'' END) AS ',
e.Name
) INTO #sql
FROM example e;
SET #sql = CONCAT('SELECT e.id_item
, ', #sql, '
from example e
GROUP BY e.id_item;');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Demo
I think You will need to develop store procedure.
Step 1 : find distinct value of 'Name' Column and store in any session variable
Step 2: use while loop and generate dynamic query
Example:
select * from (select A.id_item,if(A.Name='name1',A.Value,Null) as 'name1',if(A.Name='name2',A.Value,Null) as 'name2',if(A.Name='name3',A.Value,Null) as 'name3' from testtable A) group by id_item
I hope you get my explanation
If you have any query then comment here then I can build example in sql fiddle if needed.

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

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