我如何汇总描述栏?

时间:2016-04-21 05:04:39

标签: sql sql-server aggregate aggregate-functions

我编写了一个SQL查询,用于计算每个仓库的库存总数,如下所示。

SELECT
  InventoryItem.ItemName as 'Part Number',
  InventoryItemDescription.ItemDescription as 'Description',
  InventoryStockTotal.UnitsInStock as 'In Stock',
  InventoryStockTotal.WarehouseCode AS 'Warehouse',
  InventoryItem.Status,
  InventoryItem.AverageCost AS 'Average Cost',
  (InventoryItem.AverageCost * UnitsInStock) AS 'Stock Value'


FROM dbo.InventoryItemDescription
INNER JOIN dbo.InventoryItem
  ON InventoryItemDescription.ItemCode = InventoryItem.ItemCode
INNER JOIN dbo.InventoryStockTotal
  ON InventoryStockTotal.ItemCode = InventoryItem.ItemCode


这给我一个像这样的结果


╔═════════════╦═════════════╦══════════╦═══════════════════╦════════╦══════════════╦═════════════╗
║ Part Number ║ Description ║ In Stock ║     Warehouse     ║ Status ║ Average Cost ║ Stock Value ║
╠═════════════╬═════════════╬══════════╬═══════════════════╬════════╬══════════════╬═════════════╣
║         555 ║ FILTER      ║        0 ║ BRISBANE          ║ A      ║ 8.761043     ║ 0           ║
║         555 ║ FILTER      ║      187 ║ MAIN              ║ A      ║ 8.761043     ║ 1638.315041 ║
║         555 ║ FILTER      ║        0 ║ MELBOURNE         ║ A      ║ 8.761043     ║ 0           ║
║         555 ║ FILTER      ║       21 ║ PERTH             ║ A      ║ 8.761043     ║ 183.981903  ║
║         555 ║ FILTER      ║        0 ║ PATTISONS         ║ A      ║ 8.761043     ║ 0           ║
║         555 ║ FILTER      ║       12 ║ QLD Warehouse (1) ║ A      ║ 8.761043     ║ 105.132516  ║
║         555 ║ FILTER      ║       22 ║ SYDNEY            ║ A      ║ 8.761043     ║ 192.742946  ║
╚═════════════╩═════════════╩══════════╩═══════════════════╩════════╩══════════════╩═════════════╝


但是,我尝试编写一个查询,为每个零件编号提供TOTAL,如下所示(显然,如果我显示所有仓库的总数,则仓库代码会变得多余)

此查询按部件编号分组。

╔═════════════╦════════════════╦══════════╦════════╦══════════════╦═════════════╗
║ Part Number ║  Description   ║ In Stock ║ Status ║ Average Cost ║ Stock Value ║
╠═════════════╬════════════════╬══════════╬════════╬══════════════╬═════════════╣
║       555   ║ WIX AIR FILTER ║      242 ║ A      ║ 8.761043     ║ 2120.172406 ║
╚═════════════╩════════════════╩══════════╩════════╩══════════════╩═════════════╝

我能够开展工作的唯一问题是

SELECT
  InventoryItem.ItemName as 'Part Number',
  InventoryItem
  SUM(InventoryStockTotal.UnitsInStock) as 'In Stock',
  AVG(InventoryItem.AverageCost) AS 'Average Cost',
  (AVG(InventoryItem.AverageCost) * SUM(InventoryStockTotal.UnitsInStock)) AS 'Stock Value'

FROM dbo.InventoryItemDescription
INNER JOIN dbo.InventoryItem
  ON InventoryItemDescription.ItemCode = InventoryItem.ItemCode
INNER JOIN dbo.InventoryStockTotal
  ON InventoryStockTotal.ItemCode = InventoryItem.ItemCode

  GROUP BY InventoryItem.ItemName

这给了我这个

╔═════════════╦════════════╦══════════════╦═════════════╗
║ Part Number ║  In Stock  ║ Average Cost ║ Stock Value ║
╠═════════════╬════════════╬══════════════╬═════════════╣
║         555 ║ 242.000000 ║ 8.761043     ║ 2120.172406 ║
╚═════════════╩════════════╩══════════════╩═════════════╝

问题

我还需要在结果表中包含项目描述和状态代码等,除非我尝试将它们添加到select语句时返回错误

Column 'dbo.InventoryItemDescription.ItemDescription' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. I understand the cause of this error because its trying to group a column that doesn't have an aggregate, but how can I get around this? 

理想解决方案

对于每个实例,部件号的描述都是相同的,有什么方法可以指示SQL只选择描述的第一个实例吗?

** 编辑2 **

我可以使用SELECT DISTINCT功能吗?

1 个答案:

答案 0 :(得分:3)

如果每个部件号的描述始终相同,请不要将其添加到group by子句中。

SELECT
  InventoryItem.ItemName as 'Part Number',
  InventoryItemDescription.ItemDescription as 'Description',
  SUM(InventoryStockTotal.UnitsInStock) as 'In Stock',
  FROM ...
  GROUP BY InventoryItem.ItemName, InventoryItemDescription.ItemDescription

您可以使用SELECT DISTINCT,这与GROUP BY相同。

或者您可以利用窗口函数计算平均值/总计,同时仍保留每个描述或仓库值。

WITH CTE AS 
(
  SELECT
      InventoryItem.ItemName as 'Part Number',
      InventoryItemDescription.ItemDescription as 'Description',
      InventoryStockTotal.WarehouseCode AS 'Warehouse',
      InventoryItem.Status,
      SUM(InventoryStockTotal.UnitsInStock) OVER (PARTITION BY InventoryItem.ItemName) as 'In Stock',
      ROW_NUMBER() OVER() AS RowNumber
      FROM 
      ....
      // NO GROUP BY
)
SELECT colums
FROM CTE
WHERE RowNumber = 1