#sql #sql-server
#sql #sql-сервер
Вопрос:
У меня есть таблица с несколькими записями, я хочу получить данные за месяц вместе с подсчетом в одном из столбцов. Вывод должен содержать месяц и количество зарегистрированных флагов.
Структура таблицы
| Inserted On | IsRegistered |
------------- --------------
| 10-01-2020 | 1 |
| 15-01-2020 | 1 |
| 17-01-2020 | null |
| 17-02-2020 | 1 |
| 21-02-2020 | null |
| 04-04-2020 | null |
| 18-04-2020 | null |
| 19-04-2020 | 1 |
Исключенный вывод
| Inserted On | Registered | Not Registered
------------- ------------ ---------------
| Jan | 2 | 1
| Feb | 1 | 1
| Apr | 1 | 2
Я попытался выполнить обычную группировку, но не получил желаемого результата
SELECT
DATENAME(MONTH, dateinserted) AS [MonthName], COUNT(ISRegistered)
FROM
tablename
GROUP BY
(DATENAME(MONTH, dateinserted))
Примечание: здесь null рассматривается как не зарегистрированный
Комментарии:
1. Вы говорите, что это не дало желаемого результата; что с ним не так? Ваши ожидаемые результаты имеют 3 столбца, но вы определяете только 2 в своей попытке. Что случилось с
NotRegistered
?2. Вы выбрали нефункционирующий код. По крайней мере, исправьте это, чтобы оно работало для следующего пользователя
3. @SteveC Гордон Линофф уже предоставил исправление
Ответ №1:
Вы можете использовать агрегацию. Я бы включил год и использовал номер месяца, а не имя, поэтому:
select year(inserted_on), month(inserted_on),
coalesce(sum(is_registered), 0) as num_registered,
sum(case when is_registered is null then 1 else 0 end) as num_not_registered
from tablename
group by year(inserted_on), month(inserted_on)
order by year(inserted_on), month(inserted_on);
Примечание: Если вам действительно нужно имя месяца и вы хотите объединить данные за разные годы (что кажется маловероятным, но . . . ), тогда вы можете использовать:
select datename(month, inserted_on),
coalesce(sum(is_registered), 0) as num_registered,
sum(case when is_registered is null then 1 else 0 end) as num_not_registered
from tablename
group by datename(month, inserted_on)
order by month(min(inserted_on));
Комментарии:
1. @Gordon Linoff попробовал приведенный выше запрос, но получил ошибку — бит типа данных операнда недопустим для оператора sum. нужно ли мне приводить как int ?
2. @VishalDhasal . . . Да, вам нужно
cast()
int
.3. @Larnu . , , Это только извлечение месяца для сортировки.
Ответ №2:
ГРУППА ПО должна включать как год, так и месяц (чтобы не было перекрытия), а также ИМЯ ДАТЫ (для отображения). Что-то вроде этого
drop table if exists #tablename;
go
create table #tablename(dateinserted date, ISRegistered int);
insert #tablename values
('2020-12-01', 0),
('2020-11-02', 1),
('2020-11-03', 1),
('2020-12-01', 1),
('2020-12-03', 1),
('2020-11-02', 0);
select year(dateinserted) yr,
datename(month, dateinserted) AS [MonthName],
sum(ISRegistered) Registered ,
sum(1-ISRegistered) [Not Registered]
from #tablename
group by year(dateinserted), month(dateinserted), datename(month, dateinserted)
order by year(dateinserted), month(dateinserted);
yr MonthName Registered Not Registered
2020 November 2 1
2020 December 2 1