Display Count Each of Case When - sql-server-2008

I want display "ASO" as below:
All count must in one row
But I manage to get display "ASO" as below:
It become 2 row
My query as below to display the result:
SELECT a.ID_Company AS [COMPANY CODE],sc.Company_Name as [COMPANY NAME],
CASE WHEN a.DeptProject_Type = 'D' THEN a.ID_DeptProject END AS [DEPARTMENT],
CASE WHEN a.DeptProject_Type = 'P'THEN a.ID_DeptProject END AS [PROJECT],
CASE WHEN a.PR_Status=7THEN COUNT(a.PR_Status) END AS DRAFT,
CASE WHEN a.PR_Status=8THEN COUNT(a.PR_Status) END AS SUBMITTED,
CASE WHEN a.PR_Status=9THEN COUNT(a.PR_Status) END AS REVIEWED,
CASE WHEN a.PR_Status=10THEN COUNT(a.PR_Status) END AS CANCELLED,
CASE WHEN a.PR_Status=11THEN COUNT(a.PR_Status) END AS REJECTED,
CASE WHEN a.PR_Status=12THEN COUNT(a.PR_Status) END AS APPROVED,
CASE WHEN a.PR_Status=13THEN COUNT(a.PR_Status) END AS ENDORSED,
CASE WHEN a.PR_Status=14THEN COUNT(a.PR_Status) END AS ASSIGNED,
CASE WHEN a.PR_Status=15THEN COUNT(a.PR_Status) END AS [CLOSED],
CASE WHEN a.PR_Status=23THEN COUNT(a.PR_Status) END AS [RE-APPROVAL]
from PR_MASTER a
left join SETUP_COMPANY sc on a.ID_Company=sc.ID_Company
group by a.ID_Company,sc.Company_Name,a.ID_DeptProject,a.DeptProject_Type,a.PR_Status
order by a.ID_Company,a.PR_Status

Finally, I got the answer. Thanks to my hard-work and dedication to search the answer. Sigh
SELECT DISTINCT a.ID_Company AS [COMPANY CODE],sc.Company_Name AS [COMPANY NAME],
CASE WHEN a.DeptProject_Type = 'D' THEN a.ID_DeptProject END AS [DEPARTMENT],
CASE WHEN a.DeptProject_Type = 'P'THEN a.ID_DeptProject END AS [PROJECT],
CASE WHEN draft.Status IS NULL THEN 0 ELSE draft.Status END AS DRAFT,
CASE WHEN submitted.Status IS NULL THEN 0 ELSE submitted.Status END AS SUBMITTED,
CASE WHEN reviewed.Status IS NULL THEN 0 ELSE reviewed.Status END AS REVIEWED,
CASE WHEN cancelled.Status IS NULL THEN 0 ELSE cancelled.Status END AS CANCELLED,
CASE WHEN rejected.Status IS NULL THEN 0 ELSE rejected.Status END AS REJECTED,
CASE WHEN approved.Status IS NULL THEN 0 ELSE approved.Status END AS APPROVED,
CASE WHEN endorsed.Status IS NULL THEN 0 ELSE endorsed.Status END AS ENDORSED,
CASE WHEN ASsigned.Status IS NULL THEN 0 ELSE ASsigned.Status END AS ASSIGNED,
CASE WHEN closed.Status IS NULL THEN 0 ELSE closed.Status END AS [CLOSED],
CASE WHEN reapproval.Status IS NULL THEN 0 ELSE reapproval.Status END AS [RE-APPROVAL]
from PR_MASTER a
left join SETUP_COMPANY sc ON a.ID_Company=sc.ID_Company
left join (SELECT ID_Company,ID_DeptProject,COUNT(PR_Status) AS Status FROM PR_MASTER
WHERE PR_Status=7
GROUP BY ID_Company,ID_DeptProject) AS draft ON a.ID_Company=draft.ID_Company and a.ID_DeptProject=draft.ID_DeptProject
left join (SELECT ID_Company,ID_DeptProject,COUNT(PR_Status) AS Status FROM PR_MASTER
WHERE PR_Status=8
GROUP BY ID_Company,ID_DeptProject) AS submitted ON a.ID_Company=submitted.ID_Company and a.ID_DeptProject=submitted.ID_DeptProject
left join (SELECT ID_Company,ID_DeptProject,COUNT(PR_Status) AS Status FROM PR_MASTER
WHERE PR_Status=9
GROUP BY ID_Company,ID_DeptProject) AS reviewed ON a.ID_Company=reviewed.ID_Company and a.ID_DeptProject=reviewed.ID_DeptProject
left join (SELECT ID_Company,ID_DeptProject,COUNT(PR_Status) AS Status FROM PR_MASTER
WHERE PR_Status=10
GROUP BY ID_Company,ID_DeptProject) AS cancelled ON a.ID_Company=cancelled.ID_Company and a.ID_DeptProject=cancelled.ID_DeptProject
left join (SELECT ID_Company,ID_DeptProject,COUNT(PR_Status) AS Status FROM PR_MASTER
WHERE PR_Status=11
GROUP BY ID_Company,ID_DeptProject) AS rejected ON a.ID_Company=rejected.ID_Company and a.ID_DeptProject=rejected.ID_DeptProject
left join (SELECT ID_Company,ID_DeptProject,COUNT(PR_Status) AS Status FROM PR_MASTER
WHERE PR_Status=12
GROUP BY ID_Company,ID_DeptProject) AS approved ON a.ID_Company=approved.ID_Company and a.ID_DeptProject=approved.ID_DeptProject
left join (SELECT ID_Company,ID_DeptProject,COUNT(PR_Status) AS Status FROM PR_MASTER
WHERE PR_Status=13
GROUP BY ID_Company,ID_DeptProject) AS endorsed ON a.ID_Company=endorsed.ID_Company and a.ID_DeptProject=endorsed.ID_DeptProject
left join (SELECT ID_Company,ID_DeptProject,COUNT(PR_Status) AS Status FROM PR_MASTER
WHERE PR_Status=14
GROUP BY ID_Company,ID_DeptProject) AS ASsigned ON a.ID_Company=ASsigned.ID_Company and a.ID_DeptProject=ASsigned.ID_DeptProject
left join (SELECT ID_Company,ID_DeptProject,COUNT(PR_Status) AS Status FROM PR_MASTER
WHERE PR_Status=15
GROUP BY ID_Company,ID_DeptProject) AS closed ON a.ID_Company=closed.ID_Company and a.ID_DeptProject=closed.ID_DeptProject
left join (SELECT ID_Company,ID_DeptProject,COUNT(PR_Status) AS Status FROM PR_MASTER
WHERE PR_Status=23
GROUP BY ID_Company,ID_DeptProject) AS reapproval ON a.ID_Company=reapproval.ID_Company and a.ID_DeptProject=reapproval.ID_DeptProject
WHERE a.ID_Company IS NOT NULL
ORDER BY a.ID_Company

Related

MySQL how to pivot data to show users in database belonging to multiple groups

I'm trying to write an export script for Modx that will show members who belong to multiple groups, I've gotten this far:
select u.id, u.username, u.primary_group, mgn.name,
CASE WHEN mgn.name = 'Administrator' THEN 'TRUE' ELSE 'FALSE' END AS `Administrator`,
CASE WHEN mgn.name = 'Members' THEN 'TRUE' ELSE 'FALSE' END AS `Members`,
CASE WHEN mgn.name = 'Privileged Members' THEN 'TRUE' ELSE 'FALSE' END AS `Privileged Members`
from modx_users u
left join modx_member_groups mg on mg.member = u.id
left join modx_membergroup_names mgn on mgn.id = mg.user_group
#where u.username = 'administrator'
#group by u.username
limit 10000;
it does show the user group membership as true or false in a query, but if a user belongs to multiple groups the query will return 3 rows. If I uncomment the group by condition, it will not show TRUE for multiple groups if the member belongs to more than one group.
It is also incredibly slow. 10++ seconds on a database of about 10,000 users.
How can I fix this to show each user on a single row (in interest of exporting to CSV) and show multiple group membership?
To improve the performance you may need to add appropriate indexes to the tables. This query should do what you're looking for:
SELECT
id, username, primary_group,
CASE MAX(`Administrator`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Administrator`,
CASE MAX(`Members`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Members`,
CASE MAX(`Privileged Members`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Privileged Members`
FROM (
SELECT u.id, u.username, u.primary_group,
CASE WHEN mgn.name = 'Administrator' THEN 1 ELSE 0 END AS `Administrator`,
CASE WHEN mgn.name = 'Members' THEN 1 ELSE 0 END AS `Members`,
CASE WHEN mgn.name = 'Privileged Members' THEN 1 ELSE 0 END AS `Privileged Members`
FROM modx_users u
LEFT JOIN modx_member_groups mg on mg.member = u.id
LEFT JOIN modx_membergroup_names mgn on mgn.id = mg.user_group
) z
GROUP BY id, username, primary_group
Here is a version that removes the extra join (assuming 101, 102 and 103 are the ID values for Administrator, Members and Privileged Members, respectively) and removes username and primary_group from the grouping. It ought to perform a little better than the original, all things being equal:
SELECT
uuu.id,
uuu.username,
uuu.primary_group,
`Administrator`,
`Members`,
`Privileged Members`
FROM
modx_users uuu
LEFT JOIN
(
SELECT
z.id,
CASE MAX(`Administrator`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Administrator`,
CASE MAX(`Members`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Members`,
CASE MAX(`Privileged Members`) WHEN 1 THEN 'TRUE' ELSE 'FALSE' END AS `Privileged Members`
FROM
(
SELECT u.id,
CASE WHEN mg.user_group = 101 THEN 1 ELSE 0 END AS `Administrator`,
CASE WHEN mg.user_group = 102 THEN 1 ELSE 0 END AS `Members`,
CASE WHEN mg.user_group = 103 THEN 1 ELSE 0 END AS `Privileged Members`
FROM modx_users u
LEFT JOIN modx_member_groups mg on mg.member = u.id
) z
GROUP BY z.id
) zz on uuu.id=zz.id

Translate MYSQL query to HQL using multiple JOINS

everyone.
I am using grails 3.3.0.M2 framework with mysql as data-source the following sql query is working as expected
SELECT
c.name,
SUM(CASE
WHEN t.status = 'open' THEN 1
ELSE 0
END) 'open',
SUM(CASE
WHEN t.status = 'pending' THEN 1
ELSE 0
END) 'in progress',
SUM(CASE
WHEN t.status = 'closed' THEN 1
ELSE 0
END) 'closed'
FROM
tickets t
INNER JOIN
users u ON t.user_id = u.id
INNER JOIN
user_coordinations uc ON uc.user_id = u.id
INNER JOIN
coordinations c ON c.id = uc.coordination_id
GROUP BY 1
I translated to HQL using implicit JOIN but I am getting the wrong results, here is the hql query:
SELECT
c.name,
SUM(CASE
WHEN t.status = 'open' THEN 1
ELSE 0
END),
SUM(CASE
WHEN t.status = 'pending' THEN 1
ELSE 0
END),
SUM(CASE
WHEN t.status = 'closed' THEN 1
ELSE 0
END)
FROM
Ticket t, User u, UserCoordination uc, Coordination c
WHERE
MONTH(t.dateCreated) = :month
GROUP BY 1
In order to get the right results stack overflow users help me to understand that the query needs to use explicit JOINS, here the question: Group by a field that does not belongs to the consulted table
Right now I am trying with the following query:
SELECT
c.name,
SUM(CASE
WHEN t.status = 'open' THEN 1
ELSE 0
END),
SUM(CASE
WHEN t.status = 'pending' THEN 1
ELSE 0
END),
SUM(CASE
WHEN t.status = 'closed' THEN 1
ELSE 0
END)
FROM
Ticket t
INNER JOIN
User u
INNER JOIN
UserCoordination uc
INNER JOIN
Coordination c
WHERE
MONTH(t.dateCreated) = :month
GROUP BY 1
But i am getting a com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException with the caused message You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'inner join user_coordinations usercoordi2_ on inner join coordinations coordinat' at line 1
Thanks for your help and time
SELECT new map(
c.name as name,
(CASE
WHEN t.status = 'open' THEN 1
ELSE 0
END) as open,
(CASE
WHEN t.status = 'pending' THEN 1
ELSE 0
END) as pending,
(CASE
WHEN t.status = 'closed' THEN 1
ELSE 0
END) as closed,
SUM(open) as openSum,
SUM(pending) as pendingSum,
SUM(closed) as closedSum
)
FROM
Ticket t
left join t.user u left join u.userCoordination uc left join uc.coordination c
WHERE
MONTH(t.dateCreated) = :month
//GROUP BY 1
What you had had lots missing above is more like what you need, you need
select new map(i.item as item... if you compare the basics of this with what you had and what i tried to do you can see why you had errors.
unsure about your group by it should be group by something. Wasn't sure by inner join if you just meant a join if that was the case leave out all the left join since left join attempts to connect and get any null hasMany relations etc.

mysql use the selected variable in the same query

I have a table 'booking_summary' which stores the type of method (method = Air or Sea).
I have to join this table with one of the two other tables depending on the method column.
If the method is Air,then the table to join is booking_air,if sea then it is booking_sea.
I do not want to run multiple queries on this particular page.
This is my latest attempt,that has obviously failed.The table_name with alias is the table i want in the same query.
$sql = "select case when a.shipping_method = 'Sea' then 'booking_sea' else 'booking_air' end 'table_name',
case when a.user_id ='$active_id' then 'y' else 'no' end 'generate_access',
case when c.mbl is NULL then 'Pending' else c.mbl end 'mbl_status',
case when c.hbl is NULL then 'Pending' else c.hbl end 'hbl_status',
a.*,b.user_name
from booking_summary a
left join registered_users b
on a.user_id = b.user_id
left join table_name c
on a.id = c.id
where (a.user_id = '$active_id' or a.forwarder='$active_id')";
Any advice would be very helpful. Thanks
Om I'm not sure if this is going to work but, anyhow...
$sql = "select case
when a.user_id ='$active_id' then 'y'
else 'no' end 'generate_access',
if(a.shipping_method = 'Sea',
case when c.mbl is NULL then 'Pending' else c.mbl end,
case when d.mbl is NULL then 'Pending' else d.mbl end ) 'mbl_status',
if(a.shipping_method = 'Sea',
case when c.hbl is NULL then 'Pending' else c.hbl end,
case when d.hbl is NULL then 'Pending' else d.hbl end ) 'hbl_status',
a.*,b.user_name
from booking_summary a
left join registered_users b on a.user_id = b.user_id
left join booking_sea c on a.id = c.id
left join bookin_air d on a.id=d.id
where (a.user_id = '$active_id' or a.forwarder='$active_id')";
Without fully understanding your structure, I can think of this solution
SELECT a.shipping_method
FROM shipping_summary AS A
LEFT JOIN (SELECT *,
'AIR' AS METHOD
FROM shipping_air) AS B
ON A.shipping_method = B.method
LEFT JOIN (SELECT *,
'SEA' AS METHOD
FROM shipping_sea) AS C
ON A.shipping_method = C.method
This is a high level answer as I do not have the fields to be selected and more ways to optimise the query.

Unable to get left outer join result in mysql query

SELECT
BB.NAME BranchName,
VI.NAME Village,
COUNT(BAC.CBSACCOUNTNUMBER) 'No.Of Accounts',
SUM(BAC.CURRENTBALANCE) SumOfAmount,
SUM(CASE
WHEN transactiontype = 'C' THEN amount
ELSE 0
END) AS CreditTotal,
SUM(CASE
WHEN transactiontype = 'D' THEN amount
ELSE 0
END) AS DebitTotal,
SUM(CASE
WHEN transactiontype = 'C' THEN amount
WHEN transactiontype = 'D' THEN - 1 * amount
ELSE 0
END) AS CurrentBalance
FROM
CUSTOMER CU,
APPLICANT AP,
ADDRESS AD,
VILLAGE VI,
BANKBRANCH BB,
BANKACCOUNT BAC
LEFT OUTER JOIN
accounttransaction ACT ON BAC.CBSACCOUNTNUMBER = ACT.BANKACCOUNT_CBSACCOUNTNUMBER
AND ACT.TRANDATE <= '2013-03-21'
AND BAC.ACCOUNTOPENINGDATE < '2013-03-21'
AND ACT.BANKACCOUNT_CBSACCOUNTNUMBER IS NOT NULL
WHERE
CU.CODE = AP.CUSTOMER_CODE
AND BAC.ENTITY = 'CUSTOMER'
AND BAC.ENTITYCODE = CU.CODE
AND AD.ENTITY = 'APPLICANT'
AND AD.ENTITYCODE = AP.CODE
AND AD.VILLAGE_CODE = VI.CODE
AND AD.STATE_CODE = VI.STATE_CODE
AND AD.DISTRICT_CODE = VI.DISTRICT_CODE
AND AD.BLOCK_CODE = VI.BLOCK_CODE
AND AD.PANCHAYAT_CODE = VI.PANCHAYAT_CODE
AND CU.BANKBRANCH_CODE = BB.CODE
AND BAC.CBSACCOUNTNUMBER IS NOT NULL
AND ACT.TRANSACTIONTYPE IS NOT NULL
GROUP BY BB.NAME , VI.NAME;
Here is my information
I have two tables bankaccount and accountransactions table
If account is created it will go to bankaccount table and if any transaction is done so respective account number record in accounttrasactiosns table however I want to display the count of total account numbers respective to the branch which the account number existed in bankaccount and it is may or may not available in accounttransactions table.
I'm guessing that the problem you have is that you are not getting results for accounts that do not have data in your accounttransaction table, even though you are using a LEFT JOIN. If that is true, the reason is because your join condition includes AND ACT.BANKACCOUNT_CBSACCOUNTNUMBER IS NOT NULL, which defeats the LEFT JOIN. You also have two conditions in your WHERE clause that I bet should not be there.
You should learn to use explicit join syntax in your coding. Your code will be much clearer if you do that; it separates the join conditions from the WHERE clause, which does a very different thing. I took a stab at re-writing your query as an illustration:
SELECT
BB.NAME BranchName,
VI.NAME Village,
COUNT(BAC.CBSACCOUNTNUMBER) 'No.Of Accounts',
SUM(BAC.CURRENTBALANCE) SumOfAmount,
SUM(ACT.CurrentBalance) CurrentBalance,
SUM(ACT.DebitTotal) DebitTotal,
SUM(ACT.CreditTotal) CreditTotal
FROM CUSTOMER CU
JOIN APPLICANT AP
ON AP.CUSTOMER_CODE = CU.CODE
JOIN ADDRESS AD
ON AD.ENTITYCODE = AP.CODE
JOIN VILLAGE VI
ON VI.CODE = AD.VILLAGE_CODE
AND VI.STATE_CODE = AD.STATE_CODE
AND VI.DISTRICT_CODE = AD.DISTRICT_CODE
AND VI.BLOCK_CODE = AD.BLOCK_CODE
AND VI.PANCHAYAT_CODE = AD.PANCHAYAT_CODE
JOIN BANKBRANCH BB
ON BB.CODE = CU.BANKBRANCH_CODE
JOIN BANKACCOUNT BAC
ON BAC.ENTITYCODE = CU.CODE
LEFT OUTER JOIN (
SELECT BANKACCOUNT_CBSACCOUNTNUMBER,
SUM(CASE
WHEN transactiontype = 'C' THEN amount
ELSE 0
END) AS CreditTotal,
SUM(CASE
WHEN transactiontype = 'D' THEN amount
ELSE 0
END) AS DebitTotal,
SUM(CASE
WHEN transactiontype = 'C' THEN amount
WHEN transactiontype = 'D' THEN - 1 * amount
ELSE 0
END) AS CurrentBalance
FROM accounttransaction
WHERE TRANDATE <= '2013-03-21'
GROUP BY BANKACCOUNT_CBSACCOUNTNUMBER
) ACT
ON ACT.BANKACCOUNT_CBSACCOUNTNUMBER = BAC.CBSACCOUNTNUMBER
AND BAC.ACCOUNTOPENINGDATE < '2013-03-21'
WHERE BAC.ENTITY = 'CUSTOMER'
AND AD.ENTITY = 'APPLICANT'
GROUP BY BB.NAME , VI.NAME;
I removed this line from the LEFT JOIN condition
AND ACT.BANKACCOUNT_CBSACCOUNTNUMBER IS NOT NULL
And I removed these two lines from the WHERE clause
AND BAC.CBSACCOUNTNUMBER IS NOT NULL
AND ACT.TRANSACTIONTYPE IS NOT NULL
If that does not solve your problem, please revise your question to explain further.
UPDATE: Based on comments, the query is revised to calculate the debit, credit, and current balance by account using a derived table.
Also note the placement of the BAC.ACCOUNTOPENINGDATE < '2013-03-21' condition on left join. As written, this will return all accounts regardless of the opening date. If you want to only show accounts that were opened before that date, this condition should be moved to the WHERE clause.

Mysql COUNT result rows for a related table

I have
users
------------------------
id | name | other_stuff.....
.
engagement
------------------------
user_id | type_code |
type_code is a varchar, but either A, B, C or NULL
[ EDIT for clarity: Users can have many engagements of each type code. SO I want to count how many they have of each. ]
I want to return ALL user rows, but with a count of A, B and C type engagements. E.g.
users_result
------------------------
user_id | user_name | other_stuff..... | count_A | count_B | count_C |
I've done quite a bit of searching, but found the following issues with other solutions:
The "other_stuff..." is actually grouped / concatenated results from a dozen other joins, so it's a bit of a monster already. So I need to be able to just add the additional fields to the pre-existing "SELECT ...... FROM users..." query.
The three additional required bits of data all come from the same engagement table, each with their own condition. I havent found anything to allow me to use the three conditions on the same related table.
Thanks
[edit]
I tried to simplify the question so people didn't have to look through loads of unnecessary stuff, but seems I might not have given enough info. Here is 'most' of the original query. I've taken out a lot of the selected fields as there are loads, but I've left most of the joins in so you can see basically what is actually going on.
SELECT
user.id,
user.first_name,
user.second_name,
GROUP_CONCAT(DISTINCT illness.id ORDER BY illness.id SEPARATOR ',' ) AS reason_for_treatment,
IF(ww_id=1000003, 1,'') as user_refused_program,
Group_CONCAT(DISTINCT physical_activity.name SEPARATOR ', ') AS programme_options,
COUNT(CASE WHEN engagement_item.type_code LIKE 'wm6%' THEN 1 ELSE NULL END) as count_A,
COUNT(CASE WHEN engagement_item.type_code LIKE 'wm12%' THEN 1 ELSE NULL END) as count_B,
COUNT(CASE WHEN engagement_item.type_code LIKE 'wm6%' THEN 1 ELSE NULL END) as count_C
FROM `user`
LEFT JOIN session AS session_induction ON (user.id = session_induction.user_id AND session_induction.session_type_id = 3)
LEFT JOIN stats AS stats_induction ON session_induction.id = stats_induction.session_id
LEFT JOIN session AS session_interim ON (user.id = session_interim.user_id AND session_interim.session_type_id = 4)
LEFT JOIN stats AS stats_interim ON session_interim.id = stats_interim.session_id
LEFT JOIN session AS session_final ON (user.id = session_final.user_id AND session_final.session_type_id = 5)
LEFT JOIN stats AS stats_final ON session_final.id = stats_final.session_id
LEFT JOIN user_has_illness ON user.ID = user_has_illness.user_id
LEFT JOIN illness ON user_has_illness.illness_id = illness.id
LEFT JOIN user_has_physical_activity ON user.ID = user_has_physical_activity.user_id
LEFT JOIN physical_activity ON user_has_physical_activity.physical_activity_id = physical_activity.id
LEFT JOIN engagement_item ON user.ID = engagement_item.user_ID
WHERE (user.INDUCTION_DATE>='2010-06-09' AND user.INDUCTION_DATE<='2011-06-09' AND user.archive!='1' )
GROUP BY user.id, engagement_item.user_id
It's worth mentioning that it works fine - returns all users with all details required. Except for the count_A B and C cols.
[edit added slightly more simplified query below]
Stripped out the unrelated joins and selects.
SELECT
user.id,
user.first_name,
COUNT(CASE WHEN engagement_item.type_code LIKE 'wm6%' THEN 1 ELSE NULL END) as count_A,
COUNT(CASE WHEN engagement_item.type_code LIKE 'wm12%' THEN 1 ELSE NULL END) as count_B,
COUNT(CASE WHEN engagement_item.type_code LIKE 'wm6%' THEN 1 ELSE NULL END) as count_C
FROM `user`
LEFT JOIN engagement_item ON user.ID = engagement_item.user_ID
GROUP BY user.id, engagement_item.user_id
SELECT e.user_id, u.name,
COUNT(CASE type_code WHEN 'A' THEN 1 ELSE NULL END) as count_A,
COUNT(CASE type_code WHEN 'B' THEN 1 ELSE NULL END) as count_B,
COUNT(CASE type_code WHEN 'C' THEN 1 ELSE NULL END) as count_C
FROM engagement e join users u on (e.user_id = u.id)
GROUP BY e.user_id, u.name
I would use COUNT instead of SUM just because that is what it is made for, counting things when not NULL.
SELECT
user.id,
user.first_name,
user.second_name,
GROUP_CONCAT(DISTINCT illness.id ORDER BY illness.id SEPARATOR ',' ) AS reason_for_treatment,
IF(ww_id=1000003, 1,'') as user_refused_program,
Group_CONCAT(DISTINCT physical_activity.name SEPARATOR ', ') AS programme_options,
ei.count_A, ei.count_B, ei.count_C
FROM `user`
LEFT JOIN ( SELECT user_id
, COUNT(CASE WHEN engagement_item.type_code LIKE 'wm6%' THEN 1 ELSE NULL END) as count_A
, COUNT(CASE WHEN engagement_item.type_code LIKE 'wm12%' THEN 1 ELSE NULL END) as count_B
, COUNT(CASE WHEN engagement_item.type_code LIKE 'wm6%' THEN 1 ELSE NULL END) as count_C
FROM engagement_item
GROUP BY userid ) ei
LEFT JOIN session AS session_induction ON (user.id = session_induction.user_id AND session_induction.session_type_id = 3)
LEFT JOIN stats AS stats_induction ON session_induction.id = stats_induction.session_id
LEFT JOIN session AS session_interim ON (user.id = session_interim.user_id AND session_interim.session_type_id = 4)
LEFT JOIN stats AS stats_interim ON session_interim.id = stats_interim.session_id
LEFT JOIN session AS session_final ON (user.id = session_final.user_id AND session_final.session_type_id = 5)
LEFT JOIN stats AS stats_final ON session_final.id = stats_final.session_id
LEFT JOIN user_has_illness ON user.ID = user_has_illness.user_id
LEFT JOIN illness ON user_has_illness.illness_id = illness.id
LEFT JOIN user_has_physical_activity ON user.ID = user_has_physical_activity.user_id
LEFT JOIN physical_activity ON user_has_physical_activity.physical_activity_id = physical_activity.id
LEFT JOIN engagement_item ON user.ID = engagement_item.user_ID
WHERE (user.INDUCTION_DATE>='2010-06-09' AND user.INDUCTION_DATE<='2011-06-09' AND user.archive!='1' )
GROUP BY user.id, engagement_item.user_id, ei.count_A, ei.count_B, ei.count_C
Something like this perhaps?
select e.user_id, u.name,
sum(case e.type_code when 'A' then 1 else 0 end) as count_A,
sum(case e.type_code when 'B' then 1 else 0 end) as count_B,
sum(case e.type_code when 'C' then 1 else 0 end) as count_C
from engagement e join users u on (e.user_id = u.id)
group by e.user_id, u.name
The interesting part is the use of CASE inside the SUM to split the counting into three chunks.