我有我想象的是一个基本的SQL问题,并希望得到一些帮助。我正在使用MSSQL。
我有两张桌子:
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 :(得分: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)
答案 1 :(得分: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
答案 2 :(得分:0)
我建议使用相关子查询或apply运算符。这是方法:
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;
答案 3 :(得分:0)
我目前没有可用的SQL Server实例,因此我将发布适用于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
相等但日期不相同)。一旦组合了相等和不相等的匹配组合,外部查询将为每个max
选择最新日期(ID
)。此时,每一行ID
每行必须有一个日期,因此唯一要做的就是获得完全匹配的行。
我不知道解释计划是什么样的。 不应该是坏事,但我可能完全错了。