我将通过声明此问题类似于SQL Join on Nearest Less Than Date来解释这个问题,但那里的解决方案对我的问题不起作用。我需要根据最近的日期“过滤”表格的结果,而不是选择单个列。
我有三张桌子。主表包含以下形式的时间票据数据:
ticketId
ticketNumber
ticketDate
projectId
辅助表跟踪项目每个每日故障单上资源的费率计划。它看起来像这样:
scheduleId
projectId
effectiveDate
还有第三个表与第二个表相关,实际上包含适用的费率。像这样:
scheduleId
straightTime
overTime
在projectId上加入前两个表(显然)复制项目费率表中每条记录的数据。如果我对项目1有3个费率表,那么票据记录会产生如下结果:
ticketNumber | ticketDate | projectId | effectiveDate | scheduleId
------------- | ------------ | ----------- | -------------- | ----------
1234 | 2016-06-18 | 25 | 2016-06-01 | 1
1234 | 2016-06-18 | 25 | 2016-06-15 | 2
1234 | 2016-06-18 | 25 | 2016-06-31 | 3
使用示例:
可以直接在我的结果中选择effectiveDate SELECT *
, (SELECT TOP 1 t1.effectiveFrom
FROM dbo.labourRateSchedule t1
WHERE t1.effectiveFrom <= t2.[date] and t1.projectId = t2.projectId
ORDER BY t1.effectiveFrom desc) as effectiveDate
FROM dbo.timeTicket t2
ORDER BY t.date
但是,我需要能够将dbo.labourRateSchedule的ID加入到第三个表中,以获得适用的实际费率。将t1.ID添加到SELECT语句不会使JOIN可以访问另一个相关表。
我一直在尝试在FROM语句中加入SELECT语句,但结果只会导致最后一个effectiveDate值而不是最接近适用的ticketDate的值。
我非常感谢你们的任何帮助!
答案 0 :(得分:1)
您可以使用FROM
将子查询移动到CROSS APPLY
子句:
SELECT *
FROM dbo.timeTicket tt
CROSS APPLY
(
SELECT TOP(1) *
FROM dbo.labourRateSchedule lrs
WHERE lrs.projectId = tt.projectId
AND lrs.effectiveFrom <= tt.date
ORDER BY lrs.effectiveFrom desc
) best_lrs
JOIN dbo.schedule s on s.schedule_id = best_lrs.schedule_id
ORDER BY tt.date
答案 1 :(得分:0)
你可以尝试这样的事情(你应该改变一些东西,因为你没有发布所有信息)。
SELECT A.*, C.*
FROM timeTicket A
INNER JOIN (SELECT * , ROW_NUMBER() OVER (PARTITION BY projectId ORDER BY effectiveFrom DESC) AS RN
FROM labourRateSchedule) B ON A.projectId=B.projectId AND B.RN=1
INNER JOIN YOUR3TABLE C ON B.SCHEDULEID=C.SCHEDULEID
答案 2 :(得分:0)
你可以通过CTE和Rank功能 -
来做到这一点create table timeTicket (ticketId int,
ticketNumber int ,
ticketDate smalldatetime ,
projectId int )
go
create table labourRateSchedule
(scheduleId int,
projectId int,
effectiveDate smalldatetime )
go
create table ApplicableRates
(scheduleId int,
straightTime smalldatetime ,
overTime smalldatetime)
go
insert into timeTicket
select 1 , 1234 ,'2016-06-18' ,25
go
insert into labourRateSchedule
select 1 , 25 ,'2016-06-01'
union all select 2 , 25 ,'2016-06-15'
union all select 3 , 25 ,'2016-06-30'
go
insert into ApplicableRates
select 1 , '2016-06-07' ,'2016-06-07'
union all select 2 , '2016-06-17' ,'2016-06-17'
union all select 3 , '2016-06-22' ,'2016-06-25'
go
with cte
as (
select t1.ticketNumber ,t1.ticketDate ,t1.projectId ,t2.effectiveDate ,t3.scheduleId ,t3.straightTime
,t3.overTime , rank() over ( partition by t1.ticketNumber order by abs (DATEDIFF(day,t1.ticketDate, t2.effectiveDate) ) ) DyaDiff
from timeTicket t1 join labourRateSchedule t2
on t1.projectId = t2.projectId
join ApplicableRates t3
on t2.scheduleId = t3.scheduleId)
select * from cte where DyaDiff = 1