SQL表达式使用UNION ALL上一行的结果

时间:2016-10-01 19:43:51

标签: sql ms-access union-all

我有这两个表:

Collect: Date, Rute, Value_Collected...
Records: Date, Rute, Value, Type...

在这种情况下,其他列不相关。所以我有这个工作代码:

SELECT
Totals.Date                             AS [Date],
Sum(Totals.Collected)                   AS [Collect],
Sum(Totals.Injected)                    AS [Injections],
Sum(Totals.Spent)                       AS [Expenses],
([Collect] + [Injections]) - [Expenses] AS [Total Day]

FROM (
    SELECT
    Records.Date                        AS [Date],
    0                                   AS [Collected],
    Sum(IIF(Type =  3,Records.Value,0)) AS [Injected],
    Sum(IIF(Type <> 3,Records.Value,0)) AS [Spent]
    FROM Records GROUP BY Records.Date

    UNION ALL

    SELECT
    Collect.Date                 AS [Date],
    Sum(Collect.Value_Collected) AS [Collected],
    0                            AS [Injected],
    0                            AS [Spent]
    FROM Collect GROUP BY Collect.Date
) AS Totals GROUP BY Totals.Date

这给了我这个结果:

|Date       |Collect    |Injections  |Expenses   |Total Day
-----------------------------------------------------------
|5/09/2016  |$47.000   |$0           |$0         |$47.000 |
|6/09/2016  |$20.000   |$0           |$0         |$20.000 |
|7/09/2016  |$13.000   |$0           |$0         |$13.000 |
|11/09/2016 |$122.000  |$0           |$0         |$122.000|
|14/09/2016 |$7.000    |$0           |$0         |$7.000  |
|16/09/2016 |$100.000  |$0           |$7.000     |$93.000 |
|30/09/2016 |$0        |$80.000      |$65.000    |$15.000 |
-----------------------------------------------------------

现在还可以,但是[Total Day]列的公式必须像([Total Day Of Last Row] + [Collect] + [Injections]) - [Expenses]而不是([Collect] + [Injections]) - [Expenses]一样计算,以便给出我想要的结果:

|Date       |Collect      |Injections  |Expenses   |Total Day
-------------------------------------------------------------
|5/09/2016  |$47.000      |$0          |$0         |$47.000 |
|6/09/2016  |$20.000      |$0          |$0         |$67.000 |
|7/09/2016  |$13.000      |$0          |$0         |$80.000 |
|11/09/2016 |$122.000     |$0          |$0         |$202.000|
|14/09/2016 |$7.000       |$0          |$0         |$209.000|
|16/09/2016 |$100.000     |$0          |$7.000     |$302.000|
|30/09/2016 |$0           |$80.000     |$65.000    |$317.000|
-------------------------------------------------------------

但我不知道如何获取前一行的[Total Day]来计算当前行的[Total Day]。如果我尝试在[Totals]上运行子查询,则会出现错误,因为它无法找到表Totals。我认为这是因为它不是一个“真正的”表,但实际上我不知道如何实现这一目标。我真的很感激任何帮助。

PS:列和表的名称最初是西班牙语,但是为了便于您理解我需要完成的目的而进行翻译。

1 个答案:

答案 0 :(得分:1)

基本上,您需要通过渐进日期在字段之间累积总和,这可以使用相关的和聚合子查询来处理。唯一的挑战是MS Access没有像其他SQL方言那样的窗口函数来重用派生表查询。所以你需要在子查询中重复union派生表:

SELECT main.Date, main.Collected AS [Collect], 
       main.Injected As [Injections], main.Spent As [Expenses],
       Ccur((SELECT Sum(sub.Collected) + Sum(sub.Injected) - Sum(sub.Spent) 
             FROM 
               (SELECT Records.Date AS [Date], 0 AS [Collected],
                       Sum(IIF(Type =  3,Records.Value,0)) AS [Injected],
                       Sum(IIF(Type <> 3,Records.Value,0)) AS [Spent]
                FROM Records GROUP BY Records.Date
                UNION ALL
                SELECT Collect.Date AS [Date],
                       Sum(Collect.Value_Collected) AS [Collected],
                       0 AS [Injected],
                       0 AS [Spent]
                FROM Collect GROUP BY Collect.Date
                ) As sub
             WHERE sub.Date <= main.Date)) As [Total Day]

FROM
  (SELECT Records.Date AS [Date], 0 AS [Collected],
          Sum(IIF(Type =  3,Records.Value,0)) AS [Injected],
          Sum(IIF(Type <> 3,Records.Value,0)) AS [Spent]
   FROM Records GROUP BY Records.Date
   UNION ALL
   SELECT Collect.Date AS [Date],
         Sum(Collect.Value_Collected) AS [Collected],
         0 AS [Injected],
         0 AS [Spent]
   FROM Collect GROUP BY Collect.Date
  ) As main

幸运的是,MS Access确实维护了存储的查询对象,将UNION查询保存为单独的查询,并在新查询中引用它以获得更短的脚本:

SELECT main.Date, main.Collected As [Collect], 
       main.Injected As Injections, main.Spent As Expenses,  
       Ccur((SELECT Sum(sub.Collected) + Sum(sub.Injected) - Sum(sub.Spent) 
             FROM RecordsUnionQ As sub
             WHERE sub.Date <= main.Date)) As [Total Day]
FROM RecordsUnionQ As main

使用支持CTE的SQLite 3,您可以使用WITH()子句来保存联合查询,并避免在子查询中重复它。 CTE仅在SQL语句的持续时间内就像临时视图一样。

WITH main AS
  (SELECT Records.Date AS [Date], 0 AS [Collected],
          Sum(IIF(Type =  3,Records.Value,0)) AS [Injected],
          Sum(IIF(Type <> 3,Records.Value,0)) AS [Spent]
   FROM Records GROUP BY Records.Date
   UNION ALL
   SELECT Collect.Date AS [Date],
         Sum(Collect.Value_Collected) AS [Collected],
         0 AS [Injected],
         0 AS [Spent]
   FROM Collect GROUP BY Collect.Date)

SELECT main.Date, main.Collected AS [Collect], 
       main.Injected As [Injections], main.Spent As [Expenses],
       Ccur((SELECT Sum(sub.Collected) + Sum(sub.Injected) - Sum(sub.Spent) 
             FROM main As sub
             WHERE sub.Date <= main.Date)) As [Total Day]
FROM main;