我想查找临时表中列出的值:
所以让我们说:
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')
我需要结果是小于引用日期的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
这可以工作,但速度很慢。此外,如果行数增加,它不会一致地保留 eserial
的序列。我需要查询来保留我将其放入临时表中的顺序。
我的预期输出很简单:
其中 eserial
与临时表的序列相同,CREATEDDATETIME
是小于引用日期的最大日期。如果您了解 Excel,则更像是条件 Vlookup
。
最佳答案
不太清楚你的意思
maintain the sequence of the items in the temporary table
,但如果您想获得按 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;
为了使其快速高效地工作,请在 (ESERIAL, CREATEDDATETIME)
上向 TableSource
添加索引。索引中列的顺序很重要。
了解OUTER APPLY
查询中是否使用了任何其他列以及如何使用它们也很重要。您在问题的第一个变体中提到了列AREAID
,但在最后一个变体中没有提到。如果您确实有更多列,请清楚地表明您打算如何使用它们,因为正确的索引将取决于它。 (ESERIAL, CREATEDDATETIME)
上的索引足以满足我上面编写的查询,但如果您有更多列,则可能需要不同的索引。
如果您使用PRIMARY KEY
定义临时表,它也会对优化器有所帮助:
Create Table #mylist
(
eserial nvarchar(35) Collate SQL_Latin1_General_CP850_CI_AS PRIMARY KEY,
refdate datetime
)
主键将创建唯一的聚集索引。
还有一个重要的说明。主 TableSource
表中 ESERIAL
和 CREATEDDATETIME
列的类型和排序规则是什么?确保临时表中列的类型和排序规则与主 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
)
并在最终查询中使用ORDER BY lst.ID
。
关于sql - 拉取数据而不改变引用表中的项目顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32389446/