#sql #sql-server
#sql #sql-сервер
Вопрос:
Я перепробовал каждый поиск под солнцем, чтобы попытаться решить эту проблему, либо это, либо я неправильно ищу
У меня есть запрос с вложенным запросом, с 2 запросами объединения внутри
Пример:-
SELECT name, status , SUM(TestCount) as ‘TestCount’
FROM(
select e1.reference as reference,
e1.name as name,
e1.status as status,
, SUM(CASE WHEN e1.date IS NOT NULL THEN 1 ELSE 0 END) as TestCount
FROM dbo.table1 as e1
WHERE e1.status IN('A','B','C')
GROUP BY e1.name, e1.status
UNION ALL
select e2.reference as reference,
e2.name as name,
e2.status as status,
SUM(CASE WHEN e2.date IS NOT NULL THEN 1 ELSE 0 END) as TestCount
FROM dbo.table2 as e2
WHERE e2.status IN('A','B','C')
GROUP BY e2.name, e2.status
) t
GROUP BY Name, Status
Я хочу добавить столбец SUM CASE WHEN в мои подзапросы, затем вытащить его вверху, чтобы группировать только по имени, а не по статусу. (Поэтому, если имя пользователя отображается 5 раз для 5 разных статусов ‘, просто покажите один и тот же номер для их имени 5 раз). Проблема в том, что если я использую предложение WHERE (либо внутри), либо снаружи, оно отфильтровывает статус’, который имеет случай СУММЫ, КОГДА критерии последнего столбца
Например
Статус:-
A B C D E — ВОТ ОТКУДА БЕРЕТСЯ СУММАРНЫЙ СЛУЧАЙ, КОГДА
Я хочу использовать a, где показывать только A, B, C, D, но мне нужно количество для E..
Надеюсь, это имеет смысл
Отредактировано согласно предложению:-
SUM(CASE WHEN MONTH(Field1Date) = MONTH(GETDATE()) AND YEAR(Field1Date) = YEAR(GETDATE()) AND TypeCode IN('A', 'B', 'C') THEN 1
ELSE 0 END) OVER (PARTITION BY Name) as full_count
Затем это вызывает:-
Msg 8120, Level 16, State 1, Line 1
Column 't.Field1Date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8120, Level 16, State 1, Line 1
Column 't.Field1Date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8120, Level 16, State 1, Line 1
Column 't.TypeCode' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8120, Level 16, State 1, Line 1
Column 't.TypeCode' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8120, Level 16, State 1, Line 1
Column 't.TypeCode' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Выполнение этого уменьшает ошибку до 2:-
SUM(CASE WHEN MONTH(Field1Date) = MONTH(GETDATE()) AND YEAR(Field1Date) = YEAR(GETDATE()) AND TypeCode IN('A', 'B', 'C') THEN 1
ELSE 0 END) OVER (PARTITION BY Name, Field1Date, TypeCode) as full_count
Msg 8120, Level 16, State 1, Line 2
Column 't.Field1Date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8120, Level 16, State 1, Line 2
Column 't.TypeCode' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Я могу избавиться от последних 2 ошибок, добавив их в GROUP BY, но я не хотел ГРУППИРОВАТЬ ПО ним для начала, если это имеет смысл?
Если я добавлю их в ГРУППУ BY, чтобы устранить ошибку, сумма всегда равна 0, потому что операторы WHERE во внутренних запросах отфильтровывают все «состояния», в которых будет находиться счетчик
Извините, я должен сказать, что это SQL Server. TSQL в SSMS
Комментарии:
1.
SELECT name, status , SUM(TestCount)
2. @jarlh Это не будет отображаться, хотя, потому что TestCount отфильтровывается с использованием WHERES, поскольку не все состояния должны отображаться
3. Какую СУБД вы используете? Пожалуйста, всегда помечайте вопросы SQL той СУБД, для которой вы хотите получить ответ. Вокруг вашего псевдонима TestCount есть своего рода обратные ссылки, где стандартный SQL требует двойных кавычек. Это может указывать на MySQL. Затем, однако, вы выбираете из схемы dbo, которая типична для SQL Server. Разные СУБД имеют разные функции, поэтому нам важно знать, какую из них вы используете. Я использую стандартный SQL-запрос в своем ответе. Надеюсь, это сработает для вас.
Ответ №1:
Вы, вероятно, ищете SUM OVER
, чтобы получить общее количество по группе. Вы не сказали нам, какую СУБД вы используете, но это стандартная функция SQL, доступная во многих СУБД.
Я сократил ваш SUM(CASE WHEN date IS NOT NULL THEN 1 ELSE 0 END)
до простого COUNT(date)
. Я также удалил агрегации из внутренних запросов, поскольку вы все равно должны агрегировать в основном запросе.
SELECT
name,
status,
COUNT(date) as partial_count,
SUM(COUNT(date)) OVER (PARTITION BY name) as full_count
FROM
(
SELECT name, status, date FROM dbo.table1 WHERE status IN ('A', 'B', 'C')
UNION ALL
SELECT name, status, date FROM dbo.table2 WHERE status IN ('A', 'B', 'C')
) t
GROUP BY name, status
ORDER BY name, status;
Комментарии:
1. Это здорово, пока большое спасибо. Мой запрос намного сложнее, чем я его представлял, но я анонимизировал его для сути вопроса. Теперь я переместил всю свою сумму (СЛУЧАЙ, КОГДА) за пределы внутренних запросов во внешние запросы, это имеет гораздо больше смысла. Проблема в том, что моя сумма на самом деле равна сумме (СЛУЧАЙ, КОГДА поле 1 НЕ РАВНО НУЛЮ, а поле 2 В (‘a’, ‘b’, ‘c’), ТОГДА 1 ЕЩЕ 0 ЗАКАНЧИВАЕТСЯ) ПОВЕРХ (РАЗДЕЛА ПО имени) как full_count. Затем я получаю жалобу на GROUP BY, поэтому добавляю ее в РАЗДЕЛ ПО списку. Но он не будет выполняться, не находясь в ГРУППЕ BY
2. Добавлено больше комментариев в основной пост о том, что я пробовал @Thorsten Kettner
3. Я думаю, вам просто не хватает
SUM
. Аналитическая функцияSUM OVER
появляется после агрегированияSUM(CASE ...)
, поэтому у вас будет дваSUM
:SUM(SUM(CASE WHEN field1 IS NOT NULL and field2 IN ('a' , 'b' , 'c') THEN 1 ELSE 0 END)) OVER (PARTITION BY name)
.4. Теперь это сработало, Торстен — спасибо. Он по-прежнему показывает 0, хотя, предположительно, из-за использования WHERE. Потому что количество попадает в результаты, которые находятся в состоянии ‘D’, например. Как только я вынимаю WHERE’s, появляется счетчик рядом со статусом D
5. Значение 0 будет означать, что, хотя есть строки для статуса A, B и / или C, все их даты равны нулю.