SQL:在OVER()中使用WHERE子句?

时间:2012-04-05 10:49:58

标签: sql sql-server-2008

如何使用WHERE子句过滤OVER子句?

即。来自以下数据

LoanID | Principal | Tenor | AmortizingPrincipal 
----------------------------------------
1         20000       1       5000
1         20000       2       5000
1         20000       3       5000
1         20000       4       5000    

我需要在每个Tenor中使用Balance Principal的第四个虚拟列,如下所示:

LoanID | Principal | Tenor | AmortizingPrincipal | BalancePrinicpal 
-----------------------------------------------------------
1        20000       1       5000                  20000  
1        20000       2       5000                  15000  
1        20000       3       5000                  10000 
1        20000       4       5000                  5000

这样的事情:

SELECT 
    BalancePrincipal = Principal - SUM(AmortizingPrincipal) OVER(PARTITION BY LoanID WHERE Tenor < this row's tenor) 

更新:

以下查询为我提供了所需的结果:

SELECT 
    L1.*    
    ,BalancePrincipal = AL1.Principal - ISNULL(Cumulative.AmortizingSum,0) 
FROM
    Loan L1
CROSS APPLY 
    (
        SELECT 
            AmortizingSum = SUM(AmortizingPrincipal)
        FROM 
            Loan L2
        WHERE 
            L1.LoanID = L2.LoanID
            AND 
            L1.Tenor > L2.Tenor 
    ) Cumulative

可以更好吗?

2 个答案:

答案 0 :(得分:6)

如果您使用的是SQL Server 2012,则需要在OVER中指定ROWS / RANGE

  

通过指定分区中的起点和终点,进一步限制分区内的行。这是通过逻辑关联或物理关联指定相对于当前行的行范围来完成的。通过使用ROWS子句实现物理关联。

其他数据库系统可能具有类似的功能。此功能是2012版SQL Server中的新功能。

答案 1 :(得分:0)

对于发布的样本,它看起来不像需要过滤器:

SELECT LoanID, Principal, Tenor, AmortizingPrincipal
      ,SUM(AmortizingPrincipal) OVER(PARTITION BY LoanID ORDER BY Tenor Desc) AS BalancePrincipal
  FROM loan
  ORDER BY LoanID, Principal, Tenor

更新:

似乎Sql Server 2008没有windowing子句?我甚至认为你没有窗口条款就可以创建一个分析函数。上面的sql在Oracle和Postgres上运行没有问题。默认情况下,window子句是UNBOUNDED PRECEDING AND CURRENT ROW(from - to)。但是你可以改变顺序,然后从CURRENT ROW转到UNBOUNDED FOLLOWING。

UPDATE2:

所以我很困惑:如果你不能在分区内订购行,那么(累积)SUM在分析函数中有什么意义呢?有隐含的排序吗?我可以更改窗口(下面)并获得相同的结果,但必须提供ORDER BY(在Oracle和Postgres中)。如果没有ORDER BY,我无法看到分析SUM如何具有任何意义。

SELECT LoanID, Principal, Tenor, AmortizingPrincipal
      ,SUM(AmortizingPrincipal) OVER(PARTITION BY LoanID ORDER BY tenor
                                     RANGE BETWEEN CURRENT ROW
                                       AND UNBOUNDED FOLLOWING) AS BalancePrincipal
  FROM loan
  ORDER BY LoanID, Principal, Tenor