Как группировать строки в SQL со специальным условием?

#sql

#sql

Вопрос:

У меня в базе данных есть такая таблица:

  ----------- ------- -------- -------------- 
| Person_ID | Month |  Name  |   Special    |
 ----------- ------- -------- -------------- 
|       807 |    01 | Smith  | othercontent |
|       807 |    01 | Smith  | othercontent |
|       807 |    02 | Smith  | othercontent |
|       807 |    02 | Smith  | othercontent |
|       807 |    02 | Smith  | content      |
|       807 |    02 | Smith  | othercontent |
|       807 |    03 | Smith  | othercontent |
|       807 |    03 | Smith  | othercontent |
|       807 |    03 | Smith  | othercontent |
|       807 |    04 | Smith  | othercontent |
|       807 |    04 | Smith  | content      |
|       807 |    04 | Smith  | othercontent |
|       981 |    01 | Walker | othercontent |
|       981 |    01 | Walker | othercontent |
|       981 |    02 | Walker | othercontent |
|       981 |    02 | Walker | othercontent |
|       981 |    02 | Walker | content      |
|       981 |    02 | Walker | othercontent |
|       981 |    03 | Walker | othercontent |
|       981 |    03 | Walker | othercontent |
|       981 |    03 | Walker | othercontent |
|       981 |    04 | Walker | othercontent |
|       981 |    04 | Walker | content      |
|       981 |    04 | Walker | othercontent |
 ----------- ------- -------- -------------- 
  

Я должен написать SQL-запрос, который выбирает каждый месяц, который не содержит «содержимого» хотя бы один раз.
И он должен выдавать только одну строку.

Итак, результат должен быть таким:

  ----------- ------- -------- -------------- 
| Person_ID | Month |  Name  |   Special    |
 ----------- ------- -------- -------------- 
|       807 |    01 | Smith  | othercontent |
|       807 |    03 | Smith  | othercontent |
|       981 |    01 | Walker | othercontent |
|       981 |    03 | Walker | othercontent |
 ----------- ------- -------- -------------- 
  

Как я могу выполнить это с помощью SQL-запроса?
Я пытался сделать это с помощью функции group by, но не смог заставить ее работать должным образом.

Ответ №1:

Если вам нужна только одна строка на человека / месяц, используйте агрегацию. Вы должны использовать having предложение для фильтрации 'content' строк:

 select person_id, month, name, max(special)
from t
group by person_id, month, name
having sum(case when special = 'content' then 1 else 0 end) = 0;
  

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

1. Этот запрос отлично работает с SQLite. Однако, если я попытаюсь использовать это в Excel (Данные -> «Из других источников» -> Из Microsoft Query) и выполнить SQL-запрос, я получу синтаксическую ошибку. Проблема , по — видимому , связана с частью , начинающейся с having... . Можете ли вы объяснить, что нужно изменить?

2. @Robin . , , Это может быть потому month , что это зарезервированное слово ODB.

3. Спасибо за подсказку, но это не сработает, даже если я изменю заголовок столбца на что-то другое. В выражении запроса все еще говорится о синтаксической ошибке (отсутствующий оператор) 'sum(case when special = 'content' then 1 else 0 end) = 0'

4. @Robin . , , Код является допустимым кодом SQL Server. Что такое базовая база данных?

5. это база данных SQLite, и ваш код SQL-запроса отлично работал в моем браузере базы данных. Для попытки запустить код в Excel я просто скопировал таблицу из своего исходного сообщения в an .xlsx-file и запустил процедуру, о которой я упоминал в предыдущем комментарии.

Ответ №2:

используйте это

 select *
from t
where month not in ( select month from t as t2 where t2.special = 'content')
group by person_id, month, name, special
  

Ответ №3:

Я думаю, вам просто нужно

 select distinct *
from t t1
where not exists(select 1 from t t2 where t1.month=t2.month and t2.special = 'content')