2014-10-30 74 views
0

我有我想象的是一个有点基本的SQL问题,并希望得到一些帮助。我正在使用MSSQL。有条件的SQL加入

我有两个表:

 
Table A       Table B 
---------------------------------------------- 
A.ID |A.Date|     B.ID|B.Date|B.Number 

A.ID是独一无二的;没有重复的行。 B.ID不唯一,因此连接该列上的表可能导致返回多行。为了获得正确的记录,必须加入两栏,但这也有不良结果的问题。例如:

 
Table A    |   Table B 
---------------------------------------------- 
1  |01-01-2014  |  1 |01-01-2014|25 
2  |01-30-2014  |  1 |04-30-2013|40 
3  |03-24-2014  |  1 |10-12-2018|12 
4  |05-28-2014  |  2 |11-17-2013|55 

期望的结果是加入两列并返回一行。我遇到的问题是,如果我使用示例数据加入两个列是相等的,那么只有第一行会返回。如果我将ID列设置为相等并使用< =,则多行将返回ID 1,这是不希望的。我无法使用最大日期,因为某些字段包含将来的日期,在两个日期字段相等之前不应返回记录。在示例数据中,所需的结果将返回数字25和55.所以基本上我需要加入ID列相同和日期字段相等,但如果表B中没有相同的日期,则返回最新日期的编号,假设它不是未来的日期。

希望这是有道理的。提前致谢。

+0

那么,结果如何?你有没有得到一个适合你的答案? – ngreen 2014-10-31 16:40:43

+0

我对这个大规模的延迟表示歉意......它在一段时间里倒下了。我最终使用ROW OVER的相关子查询来分割结果,只抓取所需结果。 – user2820853 2015-07-16 19:17:47

回答

0

我会建议使用相关子查询或申请操作。下面是方法:

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

试试这个:

-- build sample data 
create table #TableA(
    ID int, 
    [Date] smalldatetime 
) 
create table #TableB(
    ID int, 
    [Date] smalldatetime, 
    number int 
) 

insert into #TableA 
select 1, '1/1/2014' union all 
select 2, '1/30/2014' union all 
select 3, '3/24/2014' union all 
select 4, '5/28/2014' 

insert into #TableB 
select 1, '1/1/2014', 25 union all 
select 1, '4/30/2013', 40 union all 
select 1, '10/12/2018', 12 union all 
select 2, '11/17/2013', 55 

-- start 
;with cte(ID, [Date], Number, rn) as(
    select 
     a.id, 
     b.date, 
     number, 
     row_number() over(
      partition by a.id 
      order by 
       case 
        when a.date = b.date then dateadd(d, 1, getdate()) 
        else b.date 
       end 
      desc     
     ) 
    from #TableA a 
    inner join #TableB b 
     on b.id = a.id 
    where 
     a.date <= getdate() 
     and b.date <= getdate() 
) 
select 
    id, 
    date, 
    number 
from cte where rn = 1 
-- end 

-- drop temp tables 
drop table #TableA 
drop table #TableB 
1

是啊,这是一个有点棘手,但这个应该这样做:在目前

with equalvalues as (
select b.* from a 
inner join b on a.ID=b.ID and a.adate=b.bdate 
), 
latestdates as (
select b.id, MAX(b.bdate) as maxbdate 
from b 
where b.bdate<=GETDATE() 
group by b.ID 
) 
select number from equalvalues 
union all 
select b.number from b 
inner join latestdates d on d.ID=b.ID and d.maxbdate=b.bdate 
where b.ID not in (select ID from equalvalues) 
0

我没有可用的SQL Server实例给我,所以我m会发布适用于PostgreSQL的语法;它应该翻译得相当好。我的目标是获得Table B的主键,然后使用主键选择该行。它适用于您提供的样本数据。我不知道你有什么规则来确定一个日期是否过于遥远,所以我输入了一个硬编码的日期,它可以轻松地交换一个绑定变量。

with KB as (
    select id as id, max(dt) as dt 
    from (
    select B.id, B.dt, B.num 
    from B 
     inner join A on A.id = B.id and A.dt = B.dt 
    union 
    select B.id, max(B.dt), B.num from B 
     inner join A on A.id = B.id and A.dt != B.dt 
    where B.dt < convert(datetime, '2014.10.313', 102) 
    group by B.id, B.num 
) subquery 
    group by id 
) 
select B.id, B.dt, B.num 
from B 
    inner join KB on KB.id = B.id and X.dt = B.dt; 

工作原理:

第一内查询只是一味地抓住精确匹配。他们需要,为什么不呢?第二个内部查询抓取所有不精确的匹配(ID相等,但日期不相等)。一旦相等的集合和不相等的集合组合起来,外部查询为每个ID挑选最新日期(max)。在这一点上,每行必须有一个单一的日期为每个ID,所以唯一要做的就是获得完全匹配的行。

我不知道这个解释计划是什么样的。它不应该坏,但我可能是完全错误的。