使用GROUP BY时使用T-SQL语句计算百分比

时间:2014-06-02 16:00:41

标签: sql sql-server tsql

在本教程的this部分中使用Microsoft SQL Server 2012的AdventureWorks2012数据库时,我想添加到示例中,并了解如何使用此查询的变体:

USE AdventureWorks2012;
GO
SELECT 
    DATEDIFF(dd,DueDate,EndDate) AS 'Days Late',
    COUNT(WorkOrderID) AS 'Late Orders',
    (COUNT(WorkOrderID) / SUM(COUNT(WorkOrderID)) AS '% of Late Orders'
 FROM Production.WorkOrder
 WHERE DueDate < EndDate
 GROUP BY DATEDIFF(dd,DueDate,EndDate)
 ORDER BY DATEDIFF(dd,DueDate,EndDate);

要使此表中“延迟订单的百分比”给出延迟一定天数的计数并将其除以所有延迟的订单,它应如下所示:

----------------------------------------
|Days Late|Late Orders|% of Late Orders|
----------------------------------------
|21       |784        |10              |
|18       |1285       |14              |
----------------------------------------

我已尝试过此查询的多个变体,查看了几个相关的StackOverflow问题,但无法在不收到错误消息的情况下使此表正常工作。 This问题让我最接近,但结果却没有了。

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

问题在于,由于您使用的是GROUP BY语句,因此所有的聚合函数都在您的子组上运行。您需要单独计算&#34;所有迟到的订单的值&#34;为了获得所有延迟订单的价值而不是具有给定延迟的所有延迟订单,可能使用CTE。

也许是这样的:

USE AdventureWorks2012;
GO

;WITH late (num_late_orders)
AS
(
    SELECT COUNT(WorkOrderID)
    FROM Production.WorkOrder
    WHERE DueDate < EndDate
)
SELECT 
    DATEDIFF(dd,DueDate,EndDate) AS 'Days Late',
    COUNT(WorkOrderID) AS 'Late Orders',
    (CAST(COUNT(WorkOrderID) AS decimal(14, 3)) / CAST(MAX(late.num_late_orders) AS decimal(14, 3))) AS '% of Late Orders'
FROM Production.WorkOrder
    CROSS JOIN late
WHERE DueDate < EndDate
GROUP BY DATEDIFF(dd,DueDate,EndDate)
ORDER BY DATEDIFF(dd,DueDate,EndDate);

您可能会对MAX() late.num_late_orders周围GROUP BY的原因感到困惑。原因是由于该值未包含在{{1}}子句中,因此必须将其包含在聚合语句中,即使该值在整个查询中保持不变。

答案 1 :(得分:1)

试试这个:

SELECT  DATEDIFF(dd,DueDate,EndDate) AS 'Days Late',
COUNT(WorkOrderID) AS 'Late Orders',
(COUNT(WorkOrderID)*1.0 / (select count(1) as TotalLateOrders FROM Production.WorkOrder
WHERE DueDate < EndDate))
AS '% of Late Orders'
FROM Production.WorkOrder
WHERE DueDate < EndDate
GROUP BY DATEDIFF(dd,DueDate,EndDate)
ORDER BY DATEDIFF(dd,DueDate,EndDate);

我乘以1.0除以花车,你也可以在之前的回答中做到这一点