How to get count for different columns on same table

It's easiest with SUM() and a CASE statement:

select CompanyName, 
sum(case when StatusID=1 then 1 else 0 end) as TotalOpenClaims,
sum(case when StatusID=2 then 1 else 0 end) as TotalClosedClaims,
sum(case when StatusID=3 then 1 else 0 end) as TotalReOpenedClaims,
sum(case when StatusID=4 then 1 else 0 end) as TotalPendingClaims
from Claims
group by CompanyName;

This is a typical pivot transformation, and conditional aggregation, as suggested by Phil, is the good old way of implementing it.

There is also a more modern syntax of achieving the same result, which uses the PIVOT clause:

SELECT
  CompanyName,
  TotalOpenClaims     = [1],
  TotalClosedClaims   = [2],
  TotalReOpenedClaims = [3],
  TotalPendingClaims  = [4]
FROM
  dbo.Claims
  PIVOT
  (
    COUNT(ClaimID)
    FOR StatusID IN ([1], [2], [3], [4])
  ) AS p
;

Internally this arguably simpler looking syntax is equivalent to Phil's GROUP BY query. More exactly, it is equivalent to this variation:

SELECT
  CompanyName,
  TotalOpenClaims     = COUNT(CASE WHEN StatusID = 1 THEN ClaimID END),
  TotalClosedClaims   = COUNT(CASE WHEN StatusID = 2 THEN ClaimID END),
  TotalReOpenedClaims = COUNT(CASE WHEN StatusID = 3 THEN ClaimID END),
  TotalPendingClaims  = COUNT(CASE WHEN StatusID = 4 THEN ClaimID END)
FROM
  dbo.Claims
GROUP BY
  CompanyName
;

So, a PIVOT query is an implicit GROUP BY query, essentially.

PIVOT queries, however, are notoriously trickier in handling than explicit GROUP BY queries with conditional aggregation. When you are using PIVOT, you need to always keep in mind this one thing:

  • All columns of the dataset being pivoted (Claims in this case) that are not explicitly mentioned in the PIVOT clause are GROUP BY columns.

If Claims consists of only the three columns shown in your example, the PIVOT query above will work as expected, because apparently CompanyName is the only column not explicitly mentioned in PIVOT and thus ends up as the only criterion of the implicit GROUP BY.

However, if Claims has other columns (say, ClaimDate), they will implicitly be used as additional GROUP BY columns – that is, your query will essentially be doing

GROUP BY CompanyName, ClaimDate, ... /* whatever other columns there are*/`

The result will most likely be not what you want.

That is easy to fix, though. In order to exclude irrelevant columns from participating in the implicit grouping, you can just use a derived table, where you will select only the columns needed for the result, although that makes the query less elegant-looking:

SELECT
  CompanyName,
  TotalOpenClaims     = [1],
  TotalClosedClaims   = [2],
  TotalReOpenedClaims = [3],
  TotalPendingClaims  = [4]
FROM
  (SELECT ClaimID, CompanyName, StatusID FROM dbo.Claims) AS derived
  PIVOT
  (
    COUNT(ClaimID)
    FOR StatusID IN ([1], [2], [3], [4])
  ) AS p
;

Still, if Claims is already a derived table, there is no need to add another level of nesting, just make sure that in the current derived table you are selecting only the columns required to produce the output.

You can read more about PIVOT in the manual: