如何与聚合函数一起选择列?

Kal*_*sin 3 sql-server aggregate-functions

假设我有一张公司表:

Company
coID | coName | coCSR
Run Code Online (Sandbox Code Playgroud)

coCSR字段是与帐户处理程序表相关的数字ID:

AccountHandler
ahID | ahFirstName | ahLastName
Run Code Online (Sandbox Code Playgroud)

我还有一张订单表:

Order
orID | orCompanyID | orDate | orValue
Run Code Online (Sandbox Code Playgroud)

现在我需要生成的输出结构如下:

Company | Account handler | No. of orders | Total of orders
Run Code Online (Sandbox Code Playgroud)

这是我试过的查询,它产生一个错误:

SELECT coID, coName, ahFirstName+' '+ahLastName AS CSRName, COUNT(orID) AS numOrders, SUM(orValue) AS totalRevenue
FROM Company
LEFT JOIN AccountHandler ON coCSR = ahID
LEFT JOIN Order ON coID = orCompanyID
WHERE coCSR = 8
AND orDate > getdate() - 365
ORDER BY coName ASC
Run Code Online (Sandbox Code Playgroud)

错误是:列名'AccountHandler.ahLastName'在ORDER BY子句中无效,因为它不包含在聚合函数中,并且没有GROUP BY子句.

如果我使用GROUP BY coID,我会在关键字'WHERE'附近获得不正确的语法.如果由于聚合函数而更改了WHEREto HAVING,我会收到错误,告诉我删除聚合函数或GROUP BY子句中未包含的每个其他列名.

我不得不承认,除了最基本的SQL命令之外,我还没有理解任何逻辑和语法,我只是试图应用我以前见过的东西,而且它不起作用.请帮我搞定这个.更好的是,你能帮助我理解为什么它现在不起作用吗?:)

And*_*y M 5

首先,您的查询可能已丢失FROM Company,但在撰写帖子时可能会以某种方式丢失.

您似乎是按公司汇总数据.因此,您需要按公司分组.您尝试分组失败的最可能原因可能是因为您放GROUP BY错了地方.我认为你之前提出过WHERE,但事实上它应该追求它(之前ORDER BY):

SELECT
  c.coID,
  c.coName,
  a.ahFirstName + ' ' + a.ahLastName AS CSRName,
  COUNT(o.orID) AS numOrders,
  SUM(o.orValue) AS totalRevenue
FROM Company c
LEFT JOIN AccountHandler a ON c.coCSR = a.ahID
LEFT JOIN [Order] o ON c.coID = o.orCompanyID
WHERE c.coCSR = 8
AND o.orDate > getdate() - 365
GROUP BY ...
ORDER BY c.coName ASC
Run Code Online (Sandbox Code Playgroud)

另一个问题是,分组是什么.SQL Server要求指定所有非聚合列GROUP BY.因此,您的GROUP BY子句应如下所示:

GROUP BY
  c.coID,
  c.coName,
  a.ahFirstName,
  a.ahLastName
Run Code Online (Sandbox Code Playgroud)

请注意,您不能通过SELECT子句中指定给它们的别名来引用列(例如CSRName).但是您可以使用ahFirstName+' '+ahLastName表达式而不是相应的列,在这种特定情况下它不会有任何区别.

如果你需要更多的非汇总列添加到这个查询,你将不得不他们两个增加SELECTGROUP BY.在某些时候,这可能会变得有点单调乏味.我建议你尝试以下方法:

SELECT
  c.coID,
  c.coName,
  a.ahFirstName + ' ' + a.ahLastName AS CSRName,
  ISNULL(o.numOrders,    0) AS numOrders,
  ISNULL(o.totalRevenue, 0) AS totalRevenue
FROM Company c
LEFT JOIN AccountHandler a ON c.coCSR = a.ahID
LEFT JOIN (
  SELECT
    orCompanyID,
    COUNT(orID)  AS numOrders,
    SUM(orValue) AS totalRevenue
  FROM [Order]
  GROUP BY
    orCompanyID
  WHERE orDate > getdate() - 365
) o ON c.coID = o.orCompanyID
WHERE c.coCSR = 8
ORDER BY c.coName ASC
Run Code Online (Sandbox Code Playgroud)

也就是说,聚合Order仅在表格上完成.然后,聚合的行集将连接到其他表.现在,您可以拉更多的属性来输出从任一CompanyAccountHandler无需担心将其添加到GROUP BY,因为不需要在该级别的任何更多的分组.