在SQL Server中匹配记录与多个记录(多个关系)

时间:2015-08-19 22:35:00

标签: sql-server

我需要将用户操作的日期与其订阅号码相匹配。 Subscription表中的一条记录与Action表中的多行相关,两者之间的链接不是月份(!)或月份+年份,因为订阅会在用户占用的几个月内持续直到新的订阅日期生效为止。

E.g。用户在2011年6月至2012年3月期间采取的所有行动日期应与2011年5月的Subscription日期相关,因为此订阅日期一直有效,直到2012年5月下一个订阅被烧毁,而这个订单持续时间另一个订单被烧焦2015年8月。

我的用户拥有不同的订阅数量,因此代码需要足够通用才能包含多个或极少数订阅与行动日期。

例如,在带有用户操作日志的tb1中,我有多条记录

Jun, 2011    (should link to Subnumber1 active between May 2011- Apr 2012)
Aug, 2011    (should link to Subnumber1 active between May 2011- Apr 2012)
Dec, 2011    (should link to Subnumber1 active between May 2011- Apr 2012)
Mar, 2012    (should link to Subnumber1 active between May 2011- Apr 2012)
May, 2012    (should link to Subnumber2 active between May 2012- Jul 2015)
Jun, 2015    (should link to Subnumber2 active between May 2012- Jul 2015)

然后在另一张表中我有用户的订阅号

May, 2011  Subnumber1
May, 2012  Subnumber2
Aug, 2015  Subnumber3

基本上,对于2012年5月发生的操作,查询应该返回Subnumber2

我很感激任何帮助!

1 个答案:

答案 0 :(得分:0)

这将为您提供所需的输出:

declare @subscription table(start_date datetime, sub varchar(10))
insert into @subscription(start_date, sub) values
('May, 2011', 'Subnumber1')
, ('May, 2012', 'Subnumber2')
, ('Aug, 2015', 'Subnumber3')

declare @action table(record datetime)
insert into @action values
('Jun, 2011'), ('Aug, 2011'), ('Dec, 2011'), ('Mar, 2012'), ('May, 2012'), ('Jun, 2015')

Select a.record, s.sub, s.start_date, s.end_date From @action as a 
Inner Join (
    Select s1.start_date, e.end_date, s1.sub from @subscription as s1
    outer apply (
        Select end_date = min(s2.start_date) from @subscription as s2
            Where s1.start_date < s2.start_date
    ) as e
) as s on a.record >= s.start_date and (a.record < s.end_date or s.end_date is null)
  

记录sub start_date end_date

     

2011-06-01 00:00:00.000 Subnumber1 2011-05-01 00:00:00.000 2012-05-01 00:00:00.000   2011-08-01 00:00:00.000 Subnumber1 2011-05-01 00:00:00.000 2012-05-01 00:00:00.000   2011-12-01 00:00:00.000 Subnumber1 2011-05-01 00:00:00.000 2012-05-01 00:00:00.000   2012-03-01 00:00:00.000 Subnumber1 2011-05-01 00:00:00.000 2012-05-01 00:00:00.000   2012-05-01 00:00:00.000 Subnumber2 2012-05-01 00:00:00.000 2015-08-01 00:00:00.000   2015-06-01 00:00:00.000 Subnumber2 2012-05-01 00:00:00.000 2015-08-01 00:00:00.000