运行总和的T-sql问题

时间:2009-10-17 21:48:04

标签: sql sql-server sql-server-2005 tsql

我正在尝试编写T-sql脚本,它将找到一个表的“打开”记录

数据结构如下

Id (int PK)      Ts (datetime)       Art_id (int)     Amount (float)
1                '2009-01-01'        1                1
2                '2009-01-05'        1                -1
3                '2009-01-10'        1                1
4                '2009-01-11'        1                -1
5                '2009-01-13'        1                1
6                '2009-01-14'        1                1
7                '2009-01-15'        2                1
8                '2009-01-17'        2                -1
9                '2009-01-18'        2                1

根据我的需要,我试图仅显示每一篇文章的最后一笔之后的记录,其中0按最后一次运行的零值的日期排序。所以我试图抽象(显示)Art_id = 1的记录5和6以及art_id = 2的记录9。我正在使用MSSQL2005,我的表有大约30K的记录,有6000个不同的ART_ID值。

3 个答案:

答案 0 :(得分:2)

在这个解决方案中,我只想找到不是的所有行,其中Art_id的后续行,其中运行总和为0.我假设我们可以使用该ID作为更好的决胜局而不是TS,因为两行可以使用相同的时间戳进入,但它们将获得顺序标识值。

;WITH base AS
(
    SELECT
        ID, Art_id, TS, Amount,
        RunningSum = Amount + COALESCE
        (
            (
               SELECT SUM(Amount)
                FROM dbo.foo
                WHERE Art_id = f.Art_id 
                AND ID < f.ID
            )
            , 0
        )
    FROM dbo.[table name] AS f
)
SELECT ID, Art_id, TS, Amount
FROM base AS b1
WHERE NOT EXISTS
(
    SELECT 1 
    FROM base AS b2 
    WHERE Art_id = b1.Art_id
    AND ID >= b1.ID
    AND RunningSum = 0
)
ORDER BY ID;

答案 1 :(得分:1)

完整的工作查询:

SELECT 
  * 
FROM TABLE_NAME E
JOIN
  (SELECT
    C.ART_ID,
    MAX(TS) MAX_TS
  FROM
    (SELECT 
      ART_ID,
      TS,
      COALESCE((SELECT SUM(AMOUNT) FROM TABLE_NAME B WHERE (B.Art_id = A.Art_id) AND (B.Ts < A.Ts)),0) ROW_SUM
    FROM TABLE_NAME A) C
  WHERE C.ROW_SUM = 0
  GROUP BY C.ART_ID) D
ON 
  (D.ART_ID = E.ART_ID) AND
  (E.TS >= D.MAX_TS)

首先我们计算每一行的运行总和:

SELECT 
  ART_ID,
  TS,
  COALESCE((SELECT SUM(AMOUNT) FROM TABLE_NAME B WHERE (B.Art_id = A.Art_id) AND (B.Ts < A.Ts)),0) ROW_SUM
FROM TABLE_NAME A

然后我们用0:

寻找上一篇文章
SELECT
  C.ART_ID,
  MAX(TS) MAX_TS
FROM
  (SELECT 
    ART_ID,
    TS,
    COALESCE((SELECT SUM(AMOUNT) FROM TABLE_NAME B WHERE (B.Art_id = A.Art_id) AND (B.Ts < A.Ts)),0) ROW_SUM
  FROM TABLE_NAME A) C
WHERE C.ROW_SUM = 0
GROUP BY C.ART_ID

答案 2 :(得分:1)

您可以找到运行总和为零的所有行:

select cur.id, cur.art_id
from @articles cur
left join @articles prev
    on prev.art_id = cur.art_id
    and prev.id <= cur.id
group by cur.id, cur.art_id
having sum(prev.amount) = 0

然后,您可以使用零运行总和查询行之后的所有行:

select a.*
from @articles a
left join (
    select cur.id, cur.art_id, running = sum(prev.amount)
    from @articles cur
    left join @articles prev
        on prev.art_id = cur.art_id
        and prev.ts <= cur.ts
    group by cur.id, cur.art_id
    having sum(prev.amount) = 0
) later_zero_running on
    a.art_id = later_zero_running.art_id
    and a.id <= later_zero_running.id
where later_zero_running.id is null

LEFT JOIN与WHERE结合使用:在此行之后不能有一行,其中运行总和为零。