Sql server 基于日期从主表中选择最近的子记录

Sql server 基于日期从主表中选择最近的子记录,sql-server,tsql,Sql Server,Tsql,我试图将数据合并到两个表中。第一个子表包含一些带有生效日期、员工编号和付款值的付款信息 emp_no date_earn Amount 456789 03/10/2009 20 456789 18/03/2010 30 456789 17/03/2011 12 456789 16/03/2012 34 另一个主表包含员工编号、生效日期和职务 emp_no effective_date job_title 456789 01/01/2009 Tester

我试图将数据合并到两个表中。第一个子表包含一些带有生效日期、员工编号和付款值的付款信息

emp_no  date_earn   Amount
456789  03/10/2009  20
456789  18/03/2010  30
456789  17/03/2011  12
456789  16/03/2012  34
另一个主表包含员工编号、生效日期和职务

emp_no  effective_date  job_title 
456789  01/01/2009      Tester
456789  20/05/2010      Manager
456789  01/04/2011      Snr Manager
我需要在薪资信息表上报告并显示在薪资信息生效日期时的职位名称:

emp_no  date_earn   Amount  job_title 
456789  03/10/2009  20      Tester
456789  18/03/2010  30      Manager
456789  17/03/2011  12      Manager
456789  16/03/2012  34      Snr Manager
我尝试过使用相关查询,例如:

select p.emp_no, p.date_earn, p.amount,
(select top 1 e.job_title from emp_hist e
where e.emp_no = p.emp_no
and e.effective_date <= p.date_earn ) as JOB_TITLE
from 
pay p where p.emp_no = 456789

但是基于上面的示例,我将为所有行提供job Tester。如果有人能帮上忙,我将不胜感激。非常感谢。

您需要从emp_hist中选择一个订单,否则第一个记录测试仪将始终满足您的条件并首先返回

where e.emp_no = p.emp_no and e.effective_date <= p.date_earn order by e.effective_date desc
然而,在这种情况下,我相信交叉应用查询可以成为您的朋友。一旦你掌握了它的用法,你就会发现自己在一次又一次地使用它。一个好的经验法则是,如果您正在考虑在内联视图中使用SELECT TOP*,请停止并使用APPLY查询。我想它会使您的SQL更易于阅读和理解,我敢说它会使您的查询更高效

您可以使用交叉应用程序重新编写查询,如下所示:

SELECT
   P.emp_no
  ,P.date_earn
  ,P.amount
  ,T.job_title
FROM
  pay P
  CROSS APPLY (
    SELECT TOP 1
      E.job_title
    FROM
      emp_hist E
    WHERE
      E.emp_no = P.emp_no
      AND E.effective_date <= P.date_earn
    ORDER BY
      E.effective_date DESC
  ) T
WHERE
  P.emp_no = 456789

我还没有运行这个程序,但我相信它应该会起作用。

在APPLY子句中缺少L。无论哪种方式都不起作用,请参见fiddle代码:。使用ORDER BY将始终返回测试仪或Snr管理器,具体取决于使用的是DESC还是ASC L?在您的小提琴中,您已经将所有日期时间声明为varchar10,这当然会打乱orderby子句。我修改了你的fiddle以使用正确的数据类型,交叉应用程序按预期工作。啊-我找到了你提到的L!是的,你是对的,在SQLFiddle上执行文本到DDL选项时没有注意到varchar。关于应该应用代码中的L:而不是APPY。现在可以用了,谢谢布雷德布雷宁,真的很感激。谢谢Yaroslav-我以前从未见过SQL小提琴!根据日期,报告上的列job_标题应为:Tester/Tester/Manager/Snr Manager