【问题标题】:Why doesn't Over() work over the sum of a column?为什么 Over() 不对列的总和起作用?
【发布时间】:2018-06-04 11:40:18
【问题描述】:

我正在尝试获取 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

【问题讨论】:

  • 我的猜测是在你调用它的时候还没有数量。
  • 另外,您永远不应该将日期转换为字符串进行比较。

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


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

     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
    

    【讨论】:

      【解决方案3】:

      我认为 Gordon 可以解决您的错误。
      您不应该将日期转换为 varchar 并进行比较。

          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
      

      【讨论】:

        猜你喜欢
        • 2022-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-19
        相关资源
        最近更新 更多