在不改变参考表中的项目序列的情况下拉取数据

L42*_*L42 6 sql sql-server sql-server-2008-r2

我想查找临时表中列出的值:

那么让我们说:

Create Table #mylist
(
eserial nvarchar(35) Collate SQL_Latin1_General_CP850_CI_AS,
refdate datetime
)

Insert Into #mylist (eserial, refdate) Values ('A', '2015-09-15')
Insert Into #mylist (eserial, refdate) Values ('B', '2015-09-14')
Insert Into #mylist (eserial, refdate) Values ('C', '2015-09-13')
Insert Into #mylist (eserial, refdate) Values ('D', '2015-09-12')
Run Code Online (Sandbox Code Playgroud)

我需要结果是Top 1小于参考日期的日期.
并且应该以与临时表中相同的顺序返回.

我尝试了什么:

Select
    lst.eserial,
    lst.refdate,
    app.CREATEDDATETIME,
From #mylist lst
Outer Apply 
    (Select Top 1 rec.CREATEDDATETIME, rec.ESERIAL, rec.ITEMID
     From TableSource rec
     Where lst.eserial=rec.ESERIAL And rec.CREATEDDATETIME<lst.refdate
     Order By rec.CREATEDDATETIME Desc
    ) As app
Run Code Online (Sandbox Code Playgroud)

这有效,但很慢.此外,如果行数增加,则不会始终保持行的顺序eserial.我需要查询来保存我把它放在临时表中的顺序.

我的预期输出再次简单:

在此输入图像描述

其中eserial与临时表的顺序相同,且CREATEDDATETIME最大日期小于参考日期.Vlookup如果您了解Excel,更像是条件.

Vla*_*nov 6

你的意思并不十分清楚

维护临时表中项目的顺序

,但如果您想获得排序的结果eserial,则必须添加ORDER BY eserial到您的查询中.没有ORDER BY结果行可以按任何顺序返回.这适用于您选择的任何方法.

因此,以您的上一个查询为基础,它将如下所示:

Select
    lst.eserial
    ,lst.refdate
    ,app.CREATEDDATETIME
From
    #mylist lst
    Outer Apply
    (
        Select Top 1 rec.CREATEDDATETIME
        From TableSource rec
        Where lst.eserial=rec.ESERIAL And rec.CREATEDDATETIME<lst.refdate
        Order By rec.CREATEDDATETIME Desc
    ) As app
ORDER BY lst.eserial;
Run Code Online (Sandbox Code Playgroud)

为了使工作快速,高效地添加一个索引TableSource(ESERIAL, CREATEDDATETIME).索引中的列顺序很重要.

了解在OUTER APPLY查询中是否存在任何其他列以及如何使用它们也很重要.您AREAID在问题的第一个变体中提到了列,但在最后一个变体中没有.如果你有更多的列,那么清楚地显示你打算如何使用它们,因为正确的索引将取决于它.(ESERIAL, CREATEDDATETIME)对于我上面写的查询,索引就足够了,但是如果你有更多列,则可能需要不同的索引.

如果您使用以下命令定义临时表,它还可以帮助优化器PRIMARY KEY:

Create Table #mylist
(
    eserial nvarchar(35) Collate SQL_Latin1_General_CP850_CI_AS PRIMARY KEY,
    refdate datetime
)
Run Code Online (Sandbox Code Playgroud)

主键将创建唯一的聚簇索引.

一个更重要的说明.列ESERIALCREATEDDATETIMETableSource表中的类型和排序规则是什么?确保临时表中列的类型和排序规则与主TableSource表匹配.如果类型不同(varchar相对nvarchardatetime相对date)或者排序规则不同,则可能不会使用索引=>它会很慢.

编辑

您在问题中多次使用短语"与临时表相同的序列",但它并不十分清楚您的意思.您的示例数据无助于解决歧义.列名eserial也增加了混乱.我可以看到两种可能的含义:

  1. 返回临时表中按行中的值排序的eserial行.
  2. 以与插入时相同的顺序从临时表中返回行.

我的原始答案暗示(1):它返回临时表中按eserial列中的值排序的行.

如果要在将行插入表中时保留行的顺序,则需要以某种方式明确记住此顺序.最简单的方法是IDENTITY在临时表中添加一列,然后按此列排序.像这样:

Create Table #mylist
(
    ID int IDENTITY PRIMARY KEY,
    eserial nvarchar(35) Collate SQL_Latin1_General_CP850_CI_AS,
    refdate datetime
)
Run Code Online (Sandbox Code Playgroud)

并在最终查询中使用ORDER BY lst.ID.