Hammad
Hammad

Reputation: 2137

Returning count of column from subquery

I have three tables:

  1. task (id, task_name, event_type_id)
  2. task_assignment (id, task_id, assignee_id,assignor_id, status)
  3. event_type

There is a strange requirement:

I want to all the tasks_assignments grouped by their event_type with the count of tasks in each event_type.

The problem is I want to get all the event types but count only for incomplete tasks.

Here is my query:

select *,count(t.id) as total
from event_type et,
  task t,
  task_assignment ta
where et.id = t.event_type_id
  and ta.task_id = t.id
  AND ta.assignee_id=" . $user_id . "
  AND ta.status!='Rejected'
group by t.event_type_id
order by total desc limit " . $limit . " offset ".$offset

What should I do?

Upvotes: 0

Views: 35

Answers (1)

SlimsGhost
SlimsGhost

Reputation: 2909

Try this (you can call it a "conditional count" - a very handy technique for this purpose):

select t.event_type_id,
    count(t.id) as total, 
    sum(case when ta.status = 'Incomplete' then 1 else 0 end) as total_incomplete
from event_type et,
  task t,
  task_assignment ta
where et.id = t.event_type_id
  and ta.task_id = t.id
  AND ta.assignee_id=" . $user_id . "
  AND ta.status!='Rejected'
group by t.event_type_id
order by total desc limit " . $limit . " offset ".$offset

Oh, and you can only select fields without aggregates (like count() and sum()) if you also group by them, so I changed your select * to select t.event_type_id. You can modify this to include whichever columns you need.

Per your comments, you could remove the filter from your WHERE clause, and do more with your "conditional counts", with whatever variations you need to fit your particular needs:

select t.event_type_id,
    count(*) as total_events, 
    sum(case when ta.status = 'Incomplete' then 1 else 0 end) as total_incomplete,
    sum(case when ta.status = 'Incomplete' 
             and ta.status != 'Rejected' then 1 else 0 end) as total_incomplete_not_rejected
    sum(case when ta.status != 'Rejected' then 1 else 0 end) as total_not_rejected
from event_type et,
  task t,
  task_assignment ta
where et.id = t.event_type_id
  and ta.task_id = t.id
  AND ta.assignee_id=" . $user_id . "
group by t.event_type_id
order by total desc limit " . $limit . " offset ".$offset

The main idea is to use SUM and conditions to get the counts for any combination of conditions - this saves you from having to do subqueries, self-joins, multiple queries, etc. Hope it helps.

Upvotes: 1

Related Questions