I have a list of emails that can belong to multiple properties in a single table.
Each email has an associated ISP, such as Gmail, Yahoo, etc.
I am trying to count how many properties an email may fall under.
In Excel, I can create a pivot table that looks how I’d like the MySQL results to look like.
Here is an example of the pivot table:
Row Labels | prop1 | prop2 | prop3 | prop4 | prop5 | grand total |
---|---|---|---|---|---|---|
email1 | 1 | 1 | 1 | 3 | ||
email2 | 1 | 1 | ||||
email3 | 1 | 1 | 1 | 1 | 4 | |
email4 | 1 | 1 |
So the above is what I am trying to achieve in MySQL. Granted, I need to include the ISP, which will be Gmail, Yahoo, etc.
The database table looks something like this:
PROPERTY | ISP | |
---|---|---|
email1 | prop1 | gm |
email2 | prop2 | yh |
email1 | prop4 | gm |
email4 | prop3 | ot |
I need to create what I did in the pivot table but in MySQL.
- I need to list out the PROPERTY as the headers
- the rows are the emails and ISP (gmail, yahoo, etc)
- then put a 1 if the email is listed under that particular property
- tally up the results
Can this be even achieved in MySQL? If so, how would I go about writing that query?
I obviously can list out the emails by writing:
SELECT `email` FROM `list_all`
That will start my email rows. I’m just not sure how to get the properties as the headers and then mark if the email is listed under that property.
Here is my attempt to write this query:
SELECT email ,
GROUP_CONCAT(CASE WHEN `property` = 'PROP1' THEN `isp_group` END) as 'PROP1',
GROUP_CONCAT(CASE WHEN `property` = 'PROP2' THEN `isp_group` END) as 'PROP2',
GROUP_CONCAT(CASE WHEN `property` = 'PROP3' THEN `isp_group` END) as 'PROP3',
GROUP_CONCAT(CASE WHEN `property` = 'PROP4' THEN `isp_group` END) as 'PROP4',
SUM(CASE WHEN `property` IN ('PROP1','PROP2','PROP3','PROP4') THEN 1 ELSE 0 END) AS TOTAL
FROM
`list_all`
WHERE `status` = 'ACTIVE'
GROUP BY = `email`
Doing the above yields the following results:
prop1 | prop2 | prop3 | prop4 | total | |
---|---|---|---|---|---|
email1 | null | null | null | null | 0 |
email2 | null | null | null | null | 0 |
email3 | null | null | null | null | 0 |
email4 | null | null | null | null | 0 |
Everything is showing up as null. This is very close to what I’ve been looking for. I just need to get rid of the nulls and replace them with either 1 or 0, and then get the totals to add up.
2
Answers
Hard to know, since the question is not precise, but you probably want conditional aggregation. It seems like you attempted that, but in order for aggregation to work (of any kind) you also need a
GROUP BY
clause.Maybe something like this:
First:
MySql Doesn’t has Pivot() table function like Sql Server has (in its new versions) but:
1- You can add some external plugin tools to it.
2- You can Use a select statement in combination with multi [case when] and an aggregation operator.
3- It exists in PostgreSQL, here is how the pivot tables are created:
Second: to get ISP use Patindex to define the ‘@’ positon number then use it inside Substring() like this:
Third: to handle Null propblem do something like this code:
More details and other ways explained in the reference:
https://popsql.com/learn-sql/sql-server/how-to-use-sql-pivot-function