AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 183015
Accepted
Ryan
Ryan
Asked: 2017-08-09 19:54:27 +0800 CST2017-08-09 19:54:27 +0800 CST 2017-08-09 19:54:27 +0800 CST

距离上次充值卡有多久了?

  • 772

我们有一张储值卡表:

CardNo   TransactionType   Amount    TransactionDate(datetime2)
         (1 for Top-up, 0 for purchasing products)
=========================================================
0001        1              1000.00    20170809(only date is displayed for brevity)
0001        0              200.00     20170810
0001        0              300.00     20170811
0001        1              200.00     20170811
0001        0              200.00     20170812

我们想知道每张卡(客户)每次购买与当时最近一次充值之间的时间。所以预期的结果是:

RowID   GapDays
================
1       Null (or 0)
2       1
3       2
4       Null
5       1

为什么 row id 为 3 有 2 天的间隔?

购买发生在充值之前。

日期列的类型为datetime2,具有“时间”部分(为简洁起见此处省略),数据按此排序。您可以使用任何索引。如有必要,将添加不存在的索引。

sql-server sql-server-2008
  • 3 3 个回答
  • 65 Views

3 个回答

  • Voted
  1. Best Answer
    McNets
    2017-08-09T23:23:10+08:002017-08-09T23:23:10+08:00

    我在TransactionDatejust 中添加了时间部分以获得正确的交易顺序:

    create table cards(CardNo varchar(10), TransactionType int, Amount money, TransactionDate datetime2);
    create index ix_cards on cards(CardNo, TransactionType, TransactionDate);
    insert into cards values
    ('0001',        1,              1000.00,    '20170809 00:00:00'),
    ('0001',        0,              200.00,     '20170810 00:00:00'),
    ('0001',        0,              300.00,     '20170811 00:00:00'),
    ('0001',        1,              200.00,     '20170811 00:00:01'),
    ('0001',        0,              200.00,     '20170812 00:00:00');
    
    GO
    
    5 行受影响
    

    然后,您可以使用APPLY包含所有记录的运算符来获取它 where TransactionType = 1。请注意,您必须将子查询返回的行限制为一条记录。

    set statistics xml on;
    
    SELECT t1.CardNo, t1.TransactionType, t1.Amount, t1.TransactionDate, t3.TransactionDate,
           DATEDIFF(DAY, t3.TransactionDate, t1.TransactionDate) GapDays
    FROM   cards t1
    OUTER APPLY (SELECT TOP 1 t2.TransactionDate
                 FROM   cards t2
                 WHERE  t2.CardNo = t1.CardNo
                 AND    t2.TransactionType = 1
                 AND    t2.TransactionDate <= t1.TransactionDate
                 ORDER BY t2.CardNo, t2.TransactionDate DESC) t3
    ORDER BY t1.CardNo, t1.TransactionType, t1.TransactionDate
    set statistics xml off;
    GO
    
    卡号 | 交易类型 | 金额 | 交易日期 | 交易日期 | 空档日
    :----- | --------------: | :-------- | :-------------------- | :-------------------- | ------:
    0001 | 0 | 200.0000 | 2017 年 10 月 8 日 00:00:00 | 09/08/2017 00:00:00 | 1个
    0001 | 0 | 300.0000 | 2017 年 11 月 8 日 00:00:00 | 09/08/2017 00:00:00 | 2个
    0001 | 0 | 200.0000 | 2017 年 12 月 8 日 00:00:00 | 2017 年 11 月 8 日 00:00:01 | 1个
    0001 | 1 | 1000.0000 | 09/08/2017 00:00:00 | 09/08/2017 00:00:00 | 0
    0001 | 1 | 200.0000 | 2017 年 11 月 8 日 00:00:01 | 2017 年 11 月 8 日 00:00:01 | 0
    
    

    执行计划

    dbfiddle在这里

    • 3
  2. sepupic
    2017-08-09T23:39:32+08:002017-08-09T23:39:32+08:00
    declare @t table (CardNo varchar(100),  TransactionType int,   Amount decimal(10,2),    TransactionDate datetime2);
        insert into @t values
        ('0001',        1,              1000.00,    '20170809'),
        ('0001',        0,              200.00,     '20170810'),
        ('0001',        0,              300.00,     '20170811 00:00:00'),
        ('0001',        1,              200.00,     '20170811 00:00:01'),
        ('0001',        0,              200.00,     '20170812');
    
    
    
    select *, datediff(day, a.top_ud_dt, TransactionDate)as gap
    from @t t1 outer apply ( select max(t2.TransactionDate) as top_ud_dt
                             from @t t2 
                             where t1.CardNo = t2.CardNo
                                   and t2.TransactionType = 1
                                   and t2.TransactionDate <= t1.TransactionDate) a;
    
    • 1
  3. KumarHarsh
    2017-08-10T20:08:00+08:002017-08-10T20:08:00+08:00
    What happen when you have multiple cardno ?give example
    

    或者,可以使用Sql server 2012 lag函数解决相同的问题。它只是为了学习窗口功能以及如何scalar expression动态

    这里不讨论性能。

    create table #cards(CardNo varchar(10), TransactionType int, Amount money
    , TransactionDate datetime2);
    create index ix_cards on #cards(CardNo, TransactionType, TransactionDate);
    insert into #cards values
    ('0001', 1, 1000.00,'20170809 00:00:00'),
    ('0001', 0, 200.00, '20170810 00:00:00'),
    ('0001', 0, 300.00, '20170811 00:00:00'),
    ('0001', 1, 200.00, '20170811 00:00:01'),
    ('0001', 0, 200.00, '20170812 00:00:00');
    
    GO
    ;
    
    WITH CTE
    AS (
        SELECT *
            ,CASE 
                WHEN TransactionType = 1
                    THEN NULL
                ELSE lag((
                            SELECT TOP 1 TransactionDate
                            FROM #cards c1
                            WHERE TransactionType = 1
                                AND c1.TransactionDate < c.TransactionDate
                            ORDER BY c1.TransactionDate DESC
                            ), 0) OVER (
                        ORDER BY c.TransactionDate DESC
                        )
                END RecentTopUp
        FROM #cards c
        )
    SELECT CardNo , TransactionType , Amount 
    , TransactionDate 
        ,datediff(day, RecentTopUp, TransactionDate) GapDays
    FROM cte
    
    
    drop table #cards
    
    • 0

相关问题

  • 死锁的主要原因是什么,可以预防吗?

  • 我在索引上放了多少“填充”?

  • 是否有开发人员遵循数据库更改的“最佳实践”类型流程?

  • 如何确定是否需要或需要索引

  • 从 SQL Server 2008 降级到 2005

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve