MS SQL:对于多个用户,如何在另一个日期(paymentdate)之前获取最新日期(billdate)?
样本表格如下: 表1MS SQL:对于多个用户,如何在另一个日期(paymentdate)之前获取最新日期(billdate)?,sql,sql-server,Sql,Sql Server,样本表格如下: 表1 userid | billdate user1 | 2017-06-01 user1 | 2017-05-01 user1 | 2017-04-01 user2 | 2017-06-01 user2 | 2017-05-01 表2 userid | paymentdate user1 | 2017-06-01 user1 | 2017-06-02 user1 | 2017-05-02 user2
userid | billdate
user1 | 2017-06-01
user1 | 2017-05-01
user1 | 2017-04-01
user2 | 2017-06-01
user2 | 2017-05-01
表2
userid | paymentdate
user1 | 2017-06-01
user1 | 2017-06-02
user1 | 2017-05-02
user2 | 2017-06-30
user2 | 2017-05-30
期望输出
userid | billdate | paymentdate
user1 | 2017-05-01 | 2017-06-01
user1 | 2017-06-01 | 2017-06-02
user1 | 2017-05-01 | 2017-05-02
user2 | 2017-06-01 | 2017-06-30
user2 | 2017-05-01 | 2017-05-30
提前谢谢
又添加了一个场景:如果在同一个月多次付款会怎么样。对于每个paymentdate,前一个账单日期应该在所需的输出中您似乎想要加入表,但没有键<代码>行号()可以提供密钥:
userid | billdate | paymentdate
user1 | 2017-05-01 | 2017-06-01
user1 | 2017-06-01 | 2017-06-02
user1 | 2017-05-01 | 2017-05-02
user2 | 2017-06-01 | 2017-06-30
user2 | 2017-05-01 | 2017-05-30
select t1.*, t2.paymentdate
from (select t1.*,
row_number() over (partition by userid order by billdate) as seqnum
from t1
) t1 join
(select t2.*,
row_number() over (partition by userid order by paymentdate) as seqnum
from t2
) t2
on t1.userid = t2.userid and t1.seqnum = t2.seqnum;
您需要从Table01中获取所有行,然后从Table02中仅获取一行。Table02行由userid和date连接(billdate有两种可能的解决方案: 弗斯特 将表格合并为一个表格。这将更清楚地显示哪些日期属于哪个账单和哪个用户。因此,所需的输出就是您正在使用的表格。如果用户已结账但尚未付款,则paymentdate为
NULL
第二
将主键添加到表1中,并将其用作表2中的外键,如下所示:
bill|u id | userid | s billdate
1 |用户1 | s 2017-06-01
2 |用户1 | s 2017-05-01
3 |用户2 | s 2017-06-01
4|用户2|s 2017-05-01
表2
userid | paymentdate
user1 | 2017-06-01
user1 | 2017-06-02
user1 | 2017-05-02
user2 | 2017-06-30
user2 | 2017-05-30
bill_id | userid |的付款日期
1 |用户1 | s 2017-06-02
2 |用户1 | s 2017-05-02
3 |用户2 | s 2017-06-30
4|用户2|s 2017-05-30
现在,您可以通过连接轻松获得它:
选择表1.*,表2.paymentdate
来自表1
左连接表2
在表1.bill\u id=table2.bill\u id;
中,如果您只想返回有账单和付款记录的记录,那么我们首先需要做一些假设-即在任何两个账单
付款之间不会有两个付款记录,或者会有两个Bill
当天付款
假设所有这些,您可以使用交叉应用
获取每个账单
记录的最新付款
记录,如果没有可用的付款
记录,则不返回任何内容:
declare @Bills table(userid nvarchar(10),billdate date);
insert into @Bills values ('user1','2017-06-01'),('user1','2017-05-01'),('user1','2017-04-01'),('user2','2017-06-01'),('user2','2017-05-01');
declare @Payments table(userid nvarchar(10),paymentdate date);
insert into @Payments values ('user1','2017-06-01'),('user1','2017-06-02'),('user1','2017-05-02'),('user2','2017-06-30'),('user2','2017-05-30');
select p.userid
,ba.billdate
,p.paymentdate
from @Payments p
cross apply(select top 1 billdate
from @Bills b
where p.userid = b.userid
and b.billdate < p.paymentdate
order by b.billdate desc
) ba
order by p.userid
,ba.billdate desc
,p.paymentdate desc;
如果user1
在表2中有三条记录,我认为你应该将你的付款链接到账单上。如果我没有账单,我永远不会付款,所以链接应该一直存在。所以基本上你必须添加一列“bill\u ID”到付款表。如果一笔交易支付多张账单,这一笔将有问题。您必须在前端应用程序上处理这一问题。可能。但假设user1只有这些记录。@Luke,是的,这是理想的方法。但是对于过去的记录,我需要获取数据。除了我的第一条评论:如果您这样做,使用第一个解决方案将不起作用k在实践中,由于一张账单可能有多笔交易,第二种解决方案几乎是复制粘贴我的评论,没有解决方案,因为OP需要查询以获取数据,而不是构建新的。如果打算进行多次支付,则无法绕过外键表。很抱歉复制了您。没有看到您的评论。若要进行多次付款,您只需要FK列。您可以将多个付款行链接到一个账单行。您只需要一个附加表就可以为一次付款提供多张账单,这在现实生活中是一种可能的情况。虽然此脚本看起来确实有效,但通常不支持只使用代码的答案。您需要解释你在做什么以及为什么。没错,只是在答案中写入代码会让StackOverflow看起来像一个它绝对不想成为的编码服务。拥有工作代码是很好的,但理解它是必不可少的。你仍然没有解释你在做什么……如果你认为你所添加的内容足以教学的话如果有人知道你的脚本是如何工作的,你最好不要回答问题。@iamdave,现在可以了吗?我希望仍然能够回答问题。谢谢你的详细回答。如果在我的现实生活场景中有多笔付款呢@HopetoChristianChophi正在更新我的答案,就在你写评论的时候:)似乎正在工作..只是用我的live db确认一下…一些live场景可能在示例场景中遗漏了。。。如果我能找到问题,将更新该问题,否则将在确认后将其标记为答案。请给我一些时间。再次感谢各位提供的快速、详细的解决方案。我已将解决方案标记为@iamdave,它对我的场景有效。由于这是我在这里的第一个问题,所以我对提供的快速响应感到不知所措。