BASIC SQL - борьба с группировкой по операторам и суммированием

Я пишу следующий сценарий SQL и обнаружил ошибку, указанную непосредственно под указанным сценарием:

  SELECT

       concat(month([sbi].[dtmDelivered]),'-',year([sbi].[dtmDelivered])) as rdate
       ,o.[strCompanyNodeName]
       ,sum(sbi.[mnyDollarcost])
       ,p.[strProductName]
       ,p.[strProductType]
       ,o.[strSalesRegionNodeGroup]
       ,o.[strSalesRegionNodeName]
       ,concat(o.[strMasterSalesFirstNameNode],' ',o.[strMasterSalesLastNameNode]) AS "Sales_Rep"  FROM [sqlSalesBI].[Fact].[uvwReport] as "sbi"

  LEFT JOIN [sqlDim].[dbo].[tbldimProduct] as "p" ON [sbi].[intDimProductPrimaryID] = p.intDimProductID
  LEFT JOIN [sqlSalesBI].[Dim].[uvwOrgNode] as "o" ON [sbi].[intOrgNodeID] = o.intOrgNodeID
  LEFT JOIN [sqlDim].[dbo].[tbldimStatus] as "t" ON [sbi].[intDimStatusID] = t.intDimStatusID

  WHERE sbi.intDimStatusID = 5 and sbi.mnyDollarcost >0 and sbi.dtmDelivered >= '2015-01-01 00:00:00.000'

  GROUP BY o.strCompanyNodeName

ОШИБКА ПОЛУЧАЮ ПРИ ВЫПОЛНЕНИИ

Msg 8120, Level 16, State 1, Line 3
Column 'sqlSalesBI.Fact.uvwReport.dtmDelivered' 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 3
Column 'sqlSalesBI.Fact.uvwReport.dtmDelivered' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

В конечном итоге я надеюсь получить конечную таблицу, в которой выручка ('mnydollarcost') суммируется и сгруппирована по месяцам и годам ('rdate'), а также по компаниям ('strCompanyNodeName').

Вот таблица, демонстрирующая, каким я хотел бы получить результат

rdate           strcompanynodename          Sum of MnyDollar Cost         other columns >>>
    ---------------------------------------------------------------------------------- 
7-2017          Chadwick Supply Co.                5100
7-2017          Northeastern Milling               5600
7-2017          Ford Paper                         25320
7-2017          Cleveland Paper Co.                1020
8-2017          Chadwick Supply Co.                1200
8-2017          Northeastern Milling               5600
8-2017          Ford Paper                         58450
8-2017          Cleveland Paper Co.                1200

Я новичок в SQL, поэтому заранее благодарим вас за терпение!

На самом деле это действительно просто. Если вы не подключаетесь к MySql, когда используется GROUP BY, тогда выбранные вами поля, которые не используются в агрегатной функции (SUM, MAX, COUNT, ...), также должны быть перечислены в GROUP BY.

LukStorms 25.07.2018 14:47

Если вы не агрегируете поле с помощью формулы агрегирования (sum(), max() и т. д.) В предложении SELECT, тогда оно ДОЛЖНО присутствовать в GROUP BY. Добавьте эти столбцы в свой пункт GROUP BY и повторите отправку.

JNevill 25.07.2018 14:54

Итак, в ответ на ваш первый комментарий я добавил в свою группу по утверждениям. Теперь он гласит: GROUP BY o. [StrCompanyNodeName], p. [StrProductName], p. [StrProductName], p. [StrProductType], o. [StrSalesRegionNodeGroup], o. [StrSalesRegionNodeName], 'rsales_rep' But все еще получаю ошибку: Msg 164, Level 15, State 1, Line 16 Каждое выражение GROUP BY должно содержать по крайней мере один столбец, который не является внешней ссылкой. @LukStorms

James 25.07.2018 14:56

@LukStorms Я поймал это примерно через 2 секунды после отправки и удалил свой комментарий.

JNevill 25.07.2018 14:56

@James Вместо использования псевдонимов, таких как rdate, используйте настоящее имя в группе by. например sbi.dtmDelivered.

LukStorms 25.07.2018 15:00

@LukStorms Святое дерьмо, это сработало, так как мой запрос выполняется без проблем. Итак, урок группы по состоит в том, чтобы никогда не использовать псевдонимы для операторов group by? Похоже, это может быть запутанным / трудным для понимания.

James 25.07.2018 15:03

Кстати, вам не нужно цитировать каждое имя с помощью [] или ". Если имя не содержит пробелов и не является ключевым словом, можно оставить их без кавычек. Хотя иногда это тоже дело вкуса.

LukStorms 25.07.2018 15:03

@ Джеймс, я согласен. И я думаю, что в некоторых реляционных базах данных разрешено использовать псевдонимы в группе by. Не в MS SQL. Если вам действительно нужно сгруппировать по псевдониму, вы можете поместить запрос в подзапрос. А затем сгруппируйте по этому псевдониму во внешнем запросе.

LukStorms 25.07.2018 15:07

Хм, хорошо. Принято к сведению. Итак, запрос завершен, и он выглядит великолепно! НО заголовок для этого столбца rdate читает «без имени столбца», что немного эстетично. Как бы переименовать без псевдонима?

James 25.07.2018 15:15

@James Вы можете дать ему псевдоним. Только не используйте этот псевдоним в группе по. например select bar * 10 as bar10, count(*) from foo group by bar в порядке. Но select bar * 10 as bar10, count(*) from foo group by bar10 не работает.

LukStorms 25.07.2018 15:20

@lukstorms понял!

James 25.07.2018 15:47
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
11
119
2

Ответы 2

Похоже, ваш запрос не агрегируется. Добавьте эти недостающие столбцы в свой ГРУППА ПО stmt, и он должен работать здесь.

Формула агрегирования работает как - поле в предложении SELECT, тогда оно ДОЛЖНО присутствовать в GROUP BY.

Как вы уже поняли, в GROUP BY не хватает нескольких:

 ... 
 GROUP BY 
    year(sbi.dtmDelivered),
   month(sbi.dtmDelivered),
   o.strCompanyNodeName,
   p.strProductName,
   p.strProductType,
   o.strSalesRegionNodeGroup,
   o.strSalesRegionNodeName,
   o.strMasterSalesFirstNameNode,
   o.strMasterSalesLastNameNode;

@James Обратите внимание, что группа не на sbi.dtmDelivered, а на году и месяце. Потому что я предполагаю, что вы захотите сгруппировать по году и месяцу, а не по дате.

LukStorms 25.07.2018 15:49

Упрощенный фрагмент теста, чтобы понять разницу: declare @T table (dt datetime); insert into @T values (GETDATE()),(GETDATE()-0.01); select year(dt)*100+month(dt) as yyyymm, count(*) as total from @T group by dt; select year(dt)*100+month(dt) as yyyymm, count(*) as total from @T group by year(dt), month(dt);

LukStorms 25.07.2018 16:16

Другие вопросы по теме