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,更像是条件.
你的意思并不十分清楚
维护临时表中项目的顺序
,但如果您想获得排序的结果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)
主键将创建唯一的聚簇索引.
一个更重要的说明.列ESERIAL
和CREATEDDATETIME
主TableSource
表中的类型和排序规则是什么?确保临时表中列的类型和排序规则与主TableSource
表匹配.如果类型不同(varchar
相对nvarchar
或datetime
相对date
)或者排序规则不同,则可能不会使用索引=>它会很慢.
编辑
您在问题中多次使用短语"与临时表相同的序列",但它并不十分清楚您的意思.您的示例数据无助于解决歧义.列名eserial
也增加了混乱.我可以看到两种可能的含义:
eserial
行.我的原始答案暗示(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
.
归档时间: |
|
查看次数: |
280 次 |
最近记录: |