【问题标题】:Need hints on seemingly simple SQL query需要关于看似简单的 SQL 查询的提示
【发布时间】:2012-05-21 14:43:21
【问题描述】:

我正在尝试做类似的事情:

SELECT c.id, c.name, COUNT(orders.id)
FROM customers c
JOIN orders o ON o.customerId = c.id

但是,SQL 不允许使用 COUNT 函数。执行时给出的错误是 c.Id 在选择列表中无效,因为它不在 group by 子句中或未聚合。

我想我知道问题所在,COUNT 只计算orders 表中的所有行。如何计算每个客户的数量?

编辑

完整查询,但它是荷兰语...这是我尝试过的:

select k.ID,
       Naam,
       Voornaam,
       Adres,
       Postcode,
       Gemeente,
       Land,
       Emailadres,
       Telefoonnummer,
       count(*) over (partition by k.id) as 'Aantal bestellingen',
       Kredietbedrag,
       Gebruikersnaam,
       k.LeverAdres,
       k.LeverPostnummer,
       k.LeverGemeente,
       k.LeverLand
from klanten k
  join bestellingen on bestellingen.klantId = k.id

没有错误但也没有结果..

【问题讨论】:

  • 查询结束时需要GROUP BY c.id, c.name
  • 您还缺少orders 表上的别名(上述查询可能无法编译)。这也导致所有答案的语法也无效。
  • @AaronBertrand 是无意的,现在已修复。
  • 强烈建议不要将'single quotes' 用于列/对象别名;此语法已被弃用。使用[square brackets],或者,如果您必须使用引号,则使用"double quotes"。或者更好的是,首先避免使用需要分隔符的别名。

标签: sql select count sql-server-2008-r2


【解决方案1】:

当使用这样的聚合函数时,您需要按任何非聚合的列进行分组:

SELECT c.id, c.name, COUNT(orders.id)
FROM customers c
JOIN orders o ON o.customerId = c.id
GROUP BY c.id, c.name

【讨论】:

  • 真的有必要吗?难道没有其他办法了吗?我不能这样做,因为我选择了几乎所有的列,当我将它们全部添加到分组依据时,查询不再返回任何内容。
  • @Mario 然后发布您的整个查询、一些示例数据和所需的结果。键入所有列应该不是问题 - 您可以简单地将 Columns 节点从对象资源管理器拖到查询窗口中。但是您需要更好地定义您的查询实际上应该返回什么。
  • @Mario - 不幸的是。我知道 MySQL 提供了一个快捷方式,如果您按主键分组,它可以让您排除其他列,但不能在 SQL Server 中。
【解决方案2】:

如果您真的希望能够在不指定名称的情况下选择 Customers 中的所有列(please read this blog post in full 是为了避免这种情况以及简单的解决方法),那么您可以改用这种惰性速记:

;WITH o AS 
(
  SELECT CustomerID, CustomerCount = COUNT(*)
  FROM dbo.Orders GROUP BY CustomerID
)
SELECT c.*, o.OrderCount
FROM dbo.Customers AS c
INNER JOIN dbo.Orders AS o
ON c.id = o.CustomerID;

编辑您的真实查询

SELECT 
  k.ID, 
  k.Naam, 
  k.Voornaam, 
  k.Adres, 
  k.Postcode, 
  k.Gemeente, 
  k.Land, 
  k.Emailadres, 
  k.Telefoonnummer,
  [Aantal bestellingen] = o.klantCount, 
  k.Kredietbedrag, 
  k.Gebruikersnaam, 
  k.LeverAdres, 
  k.LeverPostnummer, 
  k.LeverGemeente, 
  k.LeverLand
FROM klanten AS k 
INNER JOIN 
(
  SELECT klantId, klanCount = COUNT(*)
  FROM dbo.bestellingen 
  GROUP BY klantId
) AS o
ON k.id = o.klantId;

我认为这个解决方案比按所有列分组要干净得多。首先对订单表进行分组,然后对每个客户行加入一次可能比先加入然后分组更有效。

【讨论】:

  • 谢谢你,这工作非常好,而且是一个非常简洁的查询。
【解决方案3】:

以下将计算每个客户的订单,而无需按 customer.id 对整体查询进行分组。但这也意味着对于有多个订单的客户,每个订单都会重复该计数。

 SELECT c.id, c.name, COUNT(orders.id) over (partition by c.id)
 FROM customers c
   JOIN orders ON o.customerId = c.id

【讨论】:

  • "每个订单都会重复该计数。"那怎么解决呢?
  • @MarioDeSchaepmeester:那么您需要group by,如其他答案所示
猜你喜欢
  • 1970-01-01
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-26
相关资源
最近更新 更多