为什么Over()不能在列的总和上工作?

时间:2018-06-04 11:40:19

标签: sql sql-server tsql stored-procedures sql-server-2012

我试图获得TotalPrice的总和,但会抛出错误:

专栏 ' Invoices.ServicePrice'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。

ALTER PROCEDURE [dbo].[SalesReport] 

        @FromDate date= '11-May-2018',
        @ToDate date= '05-Jun-2018'

AS
BEGIN
        Set @ToDate= case when @ToDate IS NULL then Convert(varchar(11), getdate(), 106) else @ToDate end

        Select ROW_NUMBER() over (partition by b.BookingID order by b.BookingID) as ID, inv.InvoiceNo, 
        convert(varchar(11),inv.EntryDateTime,106) as EntryDateTime, Count(s.ServiceID) as TotalServices,
        SUM(inv.ServicePrice) as TotalPrice, SUM(inv.ServicePrice) over() as TotalRevenue
        from Invoices inv
        Inner Join Bookings b
        ON b.BookingID= inv.fk_BookingID
        Inner Join ZahidCarWashDB.dbo.Services s
        ON s.ServiceID= inv.fk_ServiceID
        where Convert(varchar(11), inv.EntryDateTime, 106) between @FromDate and @ToDate
        group by convert(varchar(11),inv.EntryDateTime,106), inv.InvoiceNo, b.BookingID



END

3 个答案:

答案 0 :(得分:5)

混合窗口函数和聚合函数可能很棘手。你想要的是:

SUM(inv.ServicePrice) as TotalPrice,
SUM(SUM(inv.ServicePrice)) over () as TotalRevenue

注意额外的SUM()。内部的一个是结果集中行的SUM()。外部的是窗函数,它对所有行的值求和。

答案 1 :(得分:0)

将窗口函数与聚合函数混合是个问题。你可以采取另一种方式。像这样:

 SELECT p.id, p.TotalPrice, p.TotalServices
        , SUM(p.TotalPrice) OVER (ORDER BY p.id) AS TotalPriceCumulative
        , SUM(p.TotalServices) OVER (ORDER BY P.id) AS TotalServicesCumulative
 FROM (
 SELECT b.BookingID AS ID -- or row_number() over (order By b.BookingID) AS ID
        , inv.TotalPrice, inv.TotalServices
 FROM Bookings AS b 
 INNER JOIN (SELECT inv1.fk_BookingID, SUM(inv.ServicePrice) as TotalPrice, Count(s.ServiceID) as TotalServices
                FROM Invoices AS inv1
                -- works only if one invoice is released for every invoice
                INNER Join ZahidCarWashDB.dbo.Services s ON s.ServiceID= inv1.fk_ServiceID
                where Convert(varchar(11), inv.EntryDateTime, 106) between @FromDate and @ToDate
             ) AS inv ON b.BookingID= inv.fk_BookingID
 ) AS p

答案 2 :(得分:0)

I think Gordon has the fix to your error.
You should not be converting date to varchar and do comparison.

    Set @ToDate = isnull(@ToDate, getdate());

    Select  ROW_NUMBER() over (partition by b.BookingID order by b.BookingID) as ID, 
            inv.InvoiceNo, 
            convert(varchar(11), inv.EntryDateTime, 106) as EntryDateTime, 
            Count(s.ServiceID)    as TotalServices,
            SUM(inv.ServicePrice) as TotalPrice, 
            SUM(inv.ServicePrice) over() as TotalRevenue
    from Invoices inv
    Inner Join Bookings b
       ON b.BookingID = inv.fk_BookingID
    Inner Join ZahidCarWashDB.dbo.Services s
       ON s.ServiceID = inv.fk_ServiceID
    where inv.EntryDateTime between @FromDate and @ToDate
    group by cast(inv.EntryDateTime as date)
           , inv.InvoiceNo
           , b.BookingID