SQL Server:检查上一条记录的日期

SQL Server:检查上一条记录的日期,sql,sql-server,Sql,Sql Server,我有一个SQL Server表,每当有人签出和签入卡片时,它都会在数据库中存储事务。我试图提出一个视图,以显示所有的卡交易,其中一个人没有签入一张卡在7天内的结帐。我的桌子如下所示: +-------------+-------------+------------------+ | Card_Number | Status | Transaction_Date | +-------------+-------------+------------------+ | 1234

我有一个SQL Server表,每当有人签出和签入卡片时,它都会在数据库中存储事务。我试图提出一个视图,以显示所有的卡交易,其中一个人没有签入一张卡在7天内的结帐。我的桌子如下所示:

+-------------+-------------+------------------+
| Card_Number |   Status    | Transaction_Date |
+-------------+-------------+------------------+
|      123456 | Checked In  | 7/8/2018         |
|      123456 | Checked Out | 7/1/2018         |
|      234567 | Checked In  | 7/8/2018         |
|      234567 | Checked Out | 7/1/2018         |
|      456789 | Checked In  | 7/5/2018         |
|      456789 | Checked Out | 7/1/2018         |
+-------------+-------------+------------------+
在本例中,我希望记录的卡号为123456和234567,但由于某些原因,我无法找到一个好方法来实现这一点。任何帮助都将不胜感激。先谢谢你

首先想到的是不存在:

select t.*
from t
where status = 'Checked Out' and
      not exists (select 1
                  from t t2
                  where t2.card_number = t.card_number and
                        t2.status = 'Checked In' and
                        t2.transaction_date >= t.transaction_date and
                        t2.transaction_date < dateadd(day, 7, t.transaction_date)
                 );

您是否研究过SQL Server的超前/滞后功能?这些允许轻松访问上一行或下一行

例如:

DECLARE @data TABLE ( [card_number] VARCHAR(15), [status] VARCHAR(15), [transaction_date] DATETIME );

INSERT INTO @data (
            [card_number], [status], [transaction_date]
        ) VALUES
        ( '123456', 'Checked In', '07/08/2018' )
        , ( '123456', 'Checked Out', '07/01/2018' )
        , ( '234567', 'Checked In', '07/08/2018' )
        , ( '234567', 'Checked Out', '07/01/2018' )
        , ( '456789', 'Checked In', '07/05/2018' )
        , ( '456789', 'Checked Out', '07/01/2018' );

        SELECT
            [card_number]
            , [status]
            , CONVERT( VARCHAR(10), [transaction_date], 101 ) AS [txn_date]
            , CONVERT( VARCHAR(10), LAG( [transaction_date], 1 ) OVER ( ORDER BY [card_number], [transaction_date] ), 101 ) AS [prev_txn_date]
            , CONVERT( VARCHAR(10), LEAD( [transaction_date], 1 ) OVER ( ORDER BY [card_number], [transaction_date] ), 101 ) AS [next_txn_date]
        FROM @data 
        WHERE
            [card_number] = '123456'
        ORDER BY 
            [card_number], [transaction_date];
返回:

+-------------+-------------+------------+---------------+---------------+
| card_number |   status    |  txn_date  | prev_txn_date | next_txn_date |
+-------------+-------------+------------+---------------+---------------+
|      123456 | Checked Out | 07/01/2018 | NULL          | 07/08/2018    |
|      123456 | Checked In  | 07/08/2018 | 07/01/2018    | NULL          |
+-------------+-------------+------------+---------------+---------------+

不确定我是否做对了,但这就是我所尝试的。希望有帮助

select card_number, transaction_date, sta
from
(
select t1.card_number, t1.transaction_date, t1.sta, datediff(DAY, t1.transaction_date, t2.transaction_date) as diff
from trans t1
join trans t2
on t1.card_number = t2.card_number
) result
where diff=7 and sta = 'Checked Out'

嗨,戈登,你能再解释一下关于“不存在”的用法吗?我试过你的例子,但当我使用“不存在”时,我没有得到任何回报。如果我使用“Exists”,我会返回行。@Jestes。你的问题是,我正试图提出一个视图,以显示所有卡交易,其中一个人没有在结账后7天内签入卡。这表明不存在。这接近于我正在寻找的,但我不想有一个使用卡号的where语句。可以在where语句中使用lag或lead,以便在计算中比较日期吗?更不用说我能够使其工作并满足我的需要。谢谢你的帮助。回答你的问题,是的。你已经决定了,不客气。
select card_number, transaction_date, sta
from
(
select t1.card_number, t1.transaction_date, t1.sta, datediff(DAY, t1.transaction_date, t2.transaction_date) as diff
from trans t1
join trans t2
on t1.card_number = t2.card_number
) result
where diff=7 and sta = 'Checked Out'