views:

95

answers:

5

I have a table with the following columns:

agent     status  

A          Mail Sent  
B          Fax Sent  
A          Fax Sent  
B          Mail Sent  
B          Mail Sent  
B          Fax Sent

I want to get this result:

Agent  Fax_Count    Mail_Count

A      1            1  
B      2            2
+7  A: 

You can try something like this

DECLARE @TABLE TABLE(
    agent VARCHAR(10),
    status VARCHAR(10)
)

INSERT INTO @TABLE (agent,status) SELECT 'A','Mail Sent'
INSERT INTO @TABLE (agent,status) SELECT 'B','Fax Sent'
INSERT INTO @TABLE (agent,status) SELECT 'A','Fax Sent'
INSERT INTO @TABLE (agent,status) SELECT 'B','Mail Sent'
INSERT INTO @TABLE (agent,status) SELECT 'B','Mail Sent'
INSERT INTO @TABLE (agent,status) SELECT 'B','Fax Sent' 

SELECT  agent,
     SUM(CASE WHEN status = 'Mail Sent' THEN 1 ELSE 0 END) Mail_Count ,
     SUM(CASE WHEN status = 'Fax Sent' THEN 1 ELSE 0 END) Fax_Count
FROM    @TABLE
GROUP BY agent
astander
Like this answer (better than that I was typing). The base design of the table is not very smooth to me (it doesn't seem to have a primary key, is denormalized as hell), and should probably be changed.
Romain
A: 
  select Name, SUM(MailSent),SUM(FaxSent)
  from 
  (
  select 
   case Status when 'Mail Sent' then 1 else 0 end as MailSent , 
   case Status when 'Fax Sent' then 1 else 0 end as FaxSent  ,
   Name
   from Agents
  ) tmp
Alex Reitbort
+1  A: 

As an alternative to astander's (good) solution:

SELECT  agent,
        (SELECT COUNT(*) FROM myTable WHERE agent = t.agent AND status = 'Mail Sent') Mail_Count,
        (SELECT COUNT(*) FROM myTable WHERE agent = t.agent AND status = 'Fax Sent') Fax_Count
FROM    myTable t
GROUP BY agent

Depending on the distribution of your data, performance might be better than his solution (no SUM over a calculated field) or worse (sub-selects) or equal (if the query analyzer finds the optimal execution plan in both cases).

Heinzi
+1 for not using a temp table
Mark Schultheiss
Thanks. :-) However, although I'm glad about the upvote, I should clarify that astander's solution does not *need* a temp table; he just uses it to recreate the original table of the question and illustrate his solution.
Heinzi
Good point which I observed previously, but I have found for REALLY new SQL developers, this might be confusing, not a huge thing either way.
Mark Schultheiss
Ah, I see! Yes, that makes sense.
Heinzi
A: 

You could do this... probably not the most graceful but it would work... Just swap out @Table with the table you're querying...

SELECT DISTINCT
  T.AGENT,
  (SELECT COUNT(AGENT) FROM @TABLE WHERE AGENT = T.AGENT AND Status LIKE 'Fax%') AS Fax_Count,
  (SELECT COUNT(AGENT) FROM @TABLE WHERE AGENT = T.AGENT AND Status LIKE 'Mail%') AS Email_Count
FROM
  @TABLE T
Ryan
A: 

This is the new way (since SQL Server 2005) to solve the problem by using PIVOT functionality:

SELECT agent, [Mail Sent] AS Mail_Count, [Fax Sent] AS Fax_Count
FROM 
(
  SELECT T.agent, T.status, COUNT(*) AS Counter
  FROM tblAgents AS T
  GROUP BY T.agent, T.status
) AS Data
PIVOT
(
  SUM(Counter) FOR [status] IN ([Mail Sent], [Fax Sent])
) AS PivotTable

I do not use this my self very often due to more complex syntax, but perhaps there is some performance to gain?

Joakim Backman