获取值更改时的最新日期

时间:2018-10-26 10:54:38

标签: sql sql-server tsql

我有两个客户帐户余额表,第一个有借方帐户的客户,第二个有帐户余额的详细信息。 数据将如下所示:

表A

 id_account |  balance
 -----------|---------
    1       |  -50

表B

id_account  |  data   | date
------------|---------|-----------
   1        |   -50   | 20/10/2018
   1        |   -30   | 09/10/2018
   1        |    30   | 01/10/2018
   1        |    20   | 25/09/2018
   1        |  -100   | 01/08/2018

我想知道他成为债务人的最后日期。

 id account |  balance | debit date
------------|----------|-----------
    1       |    -50   | 09/10/2018

5 个答案:

答案 0 :(得分:0)

这不完全是您想要的,但是根据示例数据,您可以执行以下操作:

select a.*, b.date as bebit_date
from tablea a outer apply
     ( select top (1) b.*
       from tableb b
       where b.id = a.id and b.data < a.balance
       order by b.date desc
     ) b;

如果我同意您的描述,我会使用row_number()

select t.id, t.balance, t.date as debit_date
from (select a.*, b.*,
             row_number() over (partition by a.id order by b.date desc) as seq
      from tablea a inner join
           tableb b
           on b.id = a.id
     ) t
where seq = 2;

答案 1 :(得分:0)

You can do it like this query

 Select 
    Id,
    balance,
    x.Date As debitDate
From TableA
Cross Apply
(
   Select top 1
         [Date]
   From TableB
   Where TableA.Id = TableB.Id
   Order by [Date] desc
) As x

答案 2 :(得分:0)

显然,您可以使用NOT EXISTS进行此操作:

SELECT a.*, debit_date
FROM @tablea AS a
OUTER APPLY (
    SELECT MIN(date) AS debit_date
    FROM @tableb AS b
    WHERE b.id_account = a.id_account
    AND   b.data < 0
    AND NOT EXISTS (
        SELECT 1
        FROM @tableb AS x
        WHERE x.id_account = b.id_account
        AND   x.date > b.date
        AND   x.data >= 0
    )
) AS OA

OUTER APPLY部分选择余额为负的所有行(-50,-30,-100),然后删除存在余额为正的新行的行(对于-100,余额为负的新行为20和30)。过滤后,您只需要最短的日期。

DB Fiddle

答案 3 :(得分:0)

更新

在Salman发表评论并使用他在答案中发布的指向DBFiddle的链接之后,我想出了一个更好的解决方案:

WITH CTE1 AS
(
    SELECT account, Data, Date, 
           ISNULL(LAG(Data) OVER(PARTITION BY account ORDER BY Date), 1) As PrevData
    FROM TableB
), CTE2 AS
(
    SELECT account, Data, Date, PrevData,
           ROW_NUMBER() OVER(PARTITION BY account ORDER BY Date DESC) As rn
    FROM CTE1
    WHERE Data < 0 AND PrevData > 0
)

SELECT a.account, balance, b.Date
FROM tablea a
LEFT JOIN CTE2 b 
    ON a.account = b.account
    AND rn = 1

请注意,比起Salman的答案要简单得多,这只是应该给出正确结果的另一个选择。请注意,如果该帐户在tableB中从来没有负数,则不会返回任何日期。

DB Fiddle link

第一版

我找到的最简单的解决方案是从TableA中选择并连接基于TableB的派生表:

SELECT a.account, balance, b.Date
FROM TableA a
JOIN (
    SELECT account, Data, Date, 
           LAG(Data) OVER(PARTITION BY account ORDER BY Date) As PrevData
    FROM TableB
) b ON a.account = b.account
WHERE b.Data < 0 AND b.PrevData > 0

答案 4 :(得分:0)

获取有关他是债务人的日期的数据,并使用Row_number()以降序列出它们。然后将输出与其他两个表合并并排在第二位将给出他作为债务人的最后日期。

SELECT DISTINCT a.id_account, a.balance, c.date FROM  #tablea a join #tableb b
ON a.id_account=b.id_account 
JOIN (SELECT b.id_account, max(b.date) date, row_number() OVER (PARTITION BY id_account ORDER BY b.date DESC) rn FROM #tableb b GROUP BY b.id_account, b.data, b.date HAVING b.data <0) c 
ON c.id_account = a.id_account 
WHERE c.rn = 2