我正在尝试找到一种有效的方法来从现有表中选择第一个相关值,就像Excel的VLOOKUP( , , , TRUE)
函数一样。这就是我所拥有的,但如果@tableWithData
与@requiredDates
相比非常大,则此代码的效率非常低。我觉得我错过了什么。有没有更好的方式来写这个:
DECLARE @requiredDates TABLE
(requiredDate datetime)
INSERT INTO @requiredDates VALUES ('2014-01-01');
INSERT INTO @requiredDates VALUES ('2014-01-15');
INSERT INTO @requiredDates VALUES ('2014-02-01');
INSERT INTO @requiredDates VALUES ('2014-02-15');
DECLARE @tableWithData TABLE
(respectiveDate datetime,
associatedValue int
)
INSERT INTO @tableWithData VALUES ('2014-01-01', 1);
INSERT INTO @tableWithData VALUES ('2014-02-01', 2);
SELECT
lookupTable.requiredDate,
dataTable.associatedValue
FROM @tableWithData as dataTable RIGHT JOIN
(
/*Create table which maps the requiredDates -> maxDate highest available date */
SELECT
dates.requiredDate,
MAX(data.respectiveDate) as maxDate/*,
data.associatedValue*/
FROM @requiredDates as dates JOIN @tableWithData as data
ON dates.requiredDate >= data.respectiveDate
GROUP BY dates.requiredDate
) as lookupTable
on lookupTable.maxDate = dataTable.respectiveDate
注意:我正在使用MS Server 2005,但如果有的话,也会感谢更通用的SQL实现。
答案 0 :(得分:0)
在Excel中,值为“TRUE”的vlookup()
会找到近似匹配项。我发现您的查询有点难以理解,但以下内容将获得小于或等于respectiveDate
字段的最大值:
SELECT dt.associatedValue,
(SELECT TOP 1 rd.requiredDate
FROM dates.requiredDate rd
WHERE rd.requiredDate <= dt.respectiveDate
ORDER BY rd.requiredDate DESC
) as RequiredDate
FROM @tableWithData dt;
查询的这种结构可以在所有数据库中使用,但需要注意TOP 1
可能需要替换为其他内容(limit
子句,fetch first 1 rows only
子句或其他内容其他)。当然,临时表不会。
在SQL Server中,您还可以使用APPLY
表达此内容。
答案 1 :(得分:0)
我正在寻找一个解决方案然后意识到,对于我所拥有的数据类型,有一个非常简单的答案,虽然它不能完全匹配您的问题,但您可能会发现它很有用。想象一下,你试图运行的查询是谁在给定日期的统治君主,你有一个君主统治的表。在excel中,你可以在一个排序的表格上进行vlookup搜索,这个表格包含了统治的开始日期或结束日期,但是在SQL中,为reign-start和reign-end查询单独的列要容易得多,然后就像
SELECT * FROM'monarchs'WHERE reign_start&gt; date AND reign_end&lt;日期
正如我所说,这是一个如此简单的查询,在某些情况下,可能值得查看数据是否可以重新配置以允许它。