2012-06-01 48 views
0

有资格[Eg]和不合格[In]的资格表[ET]中有记录。每条记录只有一个附加日期。我在服务表[ST]中有客户服务[CS],我需要确定最近服务日期之前的记录类型。查询最近处理的记录


______________ET______________ 



Eg 01.01.2012 
In 01.20.2012 
Eg 01.29.2012 
In 02.10.2012 

_________________________ST______________________________ 

CS Joe Schmoe 02.01.2012 11:00 AM 
CS Joe Schmoe 01.25.2012 1:00 PM 
CS Harold Doe 02.09.2012 4:00 PM 

我想回到一个事实,即在2012年1月2日上午11:00乔蠢货服务是因为01.01.2012的资格备案的资格,乔蠢货是没有资格2012年1月20日下午1:00,因为2012年1月20日的资格不合格记录,并且由于2012年9月2日的资格记录,Harold Schmoe有资格获得2012年9月2日下午4:00的服务。

__ _ __ _ __ _ __结果_ __ _ __ _ __ _ __ _ __ _ __

乔蠢货2012年2月1日11:00 AM资格01.01.2012
乔蠢货2012年1月25日下午1:00不合格的二○一二年一月二十〇日
哈罗德·多伊2012年9月2日4:00 PM不符合条件的2012年1月29日

+0

您的结果示例和您的描述似乎相互矛盾。 – Mithrandir

+0

因此,如果我理解正确,资格是打开或关闭。如果服务日期处于一段时间,则符合条件。如果它处于关闭期,则不是。那对吗? – mikeY

+0

ST如何加入ET? –

回答

0

假设在用户名和日期的合格表的唯一约束(否则,你需要另一个决胜局如添加ROW_NUMBER过的用户ID,日期),您:

  • JOIN到有个约会小于所有记录您感兴趣的日期(CS日期)
  • Y然后取这些日期的最大值(因为您想要事件发生前的最后一个日期)
  • 然后,您可以回到原始表格以获取行详细信息的其余部分(状态类型)。这就是为什么你需要的唯一约束

SELECT 
    UserId, Date, Status, ETDate 
FROM (
    --The last matching status record by date 
    SELECT ST.UserId, ST.Date, MAX(ET.Date) as ETDate 
    FROM ST 
    JOIN ET ON 
     ST.UserId = ET.UserId 
     AND CS.Date >= ET.Date 
    GROUP BY 
     ST.UserId, ST.Date 
) as C 
JOIN ET as E ON 
    C.UserId = E.UserId 
    AND C.ETDate = E.ETDate 
+0

没有CS表,ET表中没有用户标识。对于我们这些显然非常缓慢的人来说,你可以通过这个步骤吗? – mikeY

+0

@mikeY - 对不起 - s/CS/ST。缺少模式信息,我假设连接应该在UserId上。如果合格/不合格是一个“全局”值,应该足够简单,只需从联接中删除UserId(并且您仍然需要日期中的唯一约束)。 –

0

这似乎是一个奇怪的要求,因为elibility不是在用户级别。

下面的查询你想要做什么:

select et.*, st.elibility, st.ETDate 
from et cross join 
    (select st.* 
     from st join 
      (SELECT MAX(cs.Date) as lastcsDate 
      FROM st JOIN 
       et 
       ON st.Date <= et.Date 
      GROUP BY cs.UserId 
      ) t 
      on st.date = t.lastcsDate 
    ) lastst 

注:我没有运行此查询原谅任何错字。

这使用相关的子查询来获取et表中每个日期之前或之前的最近日期。其余的只是加入了select子句的正确信息。

2

我就是这么做的:

http://sqlfiddle.com/#!3/1c73b/5

select fname, etdate, 'eligible' as eligible 
from st 
where etdate between 
(select max(etdate) from et where status ='Eg') 
and 
(select max(etdate) from et where status ='In') 
union 
select fname, etdate, 'ineligible' as eligible 
from st 
where etdate not between 
(select max(etdate) from et where status ='Eg') 
and 
(select max(etdate) from et where status ='In') 
order by 2 
+0

使用联盟所有,因为你不会有愚蠢。也不确定这是否正确 - 你只是看最后的In/Eg行。如果你有1/10/12的etdate,他们将是“不合格” - 即使1/10的有效记录是“合格的”。 –

2

apply是专为这一点。

select 
    ST.fName, stETD = ST.etDate, previousET.* 
from 
    ST 
    outer apply (
     select top 1 
      ET.Status, 
      ET.ETDate 
     from 
      ET 
     where 
      ET.ETDate <= ST.etDate 
     order by 
      ET.ETDate desc 
    ) previousET 
order by 
    2 

http://sqlfiddle.com/#!3/1c73b/11

这将让你最近(order by ETDate desc)诉讼记录(where ETDate <= ST.Date)。感谢mikeY为小提琴。

+0

如果清理列名称,那在我的小提琴中起作用。很酷。 – mikeY

+0

+1为清楚起见,但我通常不喜欢相关的子查询(这基本上是适用的归结) –