использование where в count sql

#sql #sql-server #tsql

#sql #sql-сервер #tsql

Вопрос:

У меня есть этот SQL, который работает нормально

 SELECT COUNT(*) AS total, e.FirstName, e.LastName
FROM [Messages] AS m 
INNER JOIN Employees AS e ON m.SenderId = e.UserId
GROUP BY e.EmployeeId, e.FirstName, e.LastName
  

Но я хочу также иметь общее количество непрочитанных сообщений в виде столбца.

Как я могу достичь этого в SQL?

 SELECT 
    COUNT(*) AS total,
    COUNT(where m.isRead = false) AS totalUnreadMessages,
    e.FirstName, e.LastName
FROM 
    [Messages] AS m 
INNER JOIN
    Employees AS e ON m.SenderId = e.UserId
GROUP BY
    e.EmployeeId, e.FirstName, e.LastName
  

Комментарии:

1. почему голосование против? что не так с моим вопросом?

2. Вы, кажется, довольно обеспокоены производительностью ответов. Я бы рискнул предположить, что логика подсчета непрочитанных сообщений несущественна по сравнению с остальной частью запроса, т.е. INNER JOIN и GROUP BY . Вы можете изучить планы выполнения с дополнительной логикой и без нее, чтобы увидеть влияние. ИМХО, я нахожу ответ доктора Линоффа более четким изложением ваших намерений. Ответ от Jarth, хотя и функционально правильный, основан на CASE возврате значения по умолчанию NULL и COUNT не агрегировании NULL значений.

Ответ №1:

Вы почти на месте, используйте case выражение для выполнения условного подсчета:

 SELECT Count(*) as total,Count(case when m.isRead = false then 1 end) as totalUnreadMessage,
    e.FirstName,e.LastName
FROM [Messages] as m 
inner join Employees as e on m.SenderId=e.UserId
group by e.EmployeeId, e.FirstName,e.LastName
  

Комментарии:

1. Я бы этого не ожидал. (Зависит от данных, индексов и т.д.)

Ответ №2:

Я бы написал это как:

 SELECT e.FirstName, e.LastName, COUNT(*) as total,
       SUM(CASE WHEN m.isRead = 0 THEN 1 ELSE 0 END) as total_unread
FROM [Messages] m JOIN
     Employees e 
     ON m.SenderId = e.UserId
GROUP BY e.EmployeeId, e.FirstName, e.LastName;
  

Комментарии:

1. @user6599525 . . . По сравнению с чем? Драйвером производительности для запроса является агрегирование, а не вычисления в SELECT .

2. в сравнении с count ?

Ответ №3:

Вы можете посчитать их, а затем объединить с исходным select:

 SELECT Count(*) as total,tbNotRead.NotReadNumber AS totalUnreadMessage, e.FirstName,e.LastName
FROM [Messages] as m 
INNER JOIN Employees as e ON m.SenderId=e.UserId
LEFT OUTER JOIN
(
  SELECT m.Sender, COUNT(*) NotReadNumber
  FROM [Messages] msgs
  WHERE m.isRead = FALSE
  GROUP BY m.Sender
)tbNotRead
ON tbNotRear.Sender = m.sender
GROUP BY e.EmployeeId, e.FirstName,e.LastName, tbNotRead.NotReadNumber