我用一种非常基本且低效的方式编写了这个T-SQL查询:
SELECT
e.ExchangeId,
e.ExchangeName,
s.StockId,
s.StockName,
sp.StockDate,
sp.StockPrice,
DATEADD(YEAR, -3, sp.StockDate) AS YearTDate,
(SELECT spm.StockPrice FROM dbo.StockPrices spm WITH(NOLOCK) WHERE (spm.StockId = sp.StockId) AND (spm.StockDate = DATEADD(YEAR, -3, sp.StockDate))) AS YearTPrice,
(SELECT TOP 1 spm.StockDate FROM dbo.StockPrices spm WITH(NOLOCK) WHERE (spm.StockId = sp.StockId) AND (spm.StockDate = DATEADD(YEAR, -3, sp.StockDate)) ORDER BY spm.StockPriceId) AS LatestDate,
(SELECT TOP 1 spm.StockPrice FROM dbo.StockPrices spm WITH(NOLOCK) WHERE (spm.StockId = sp.StockId) AND (spm.StockDate = DATEADD(YEAR, -3, sp.StockDate)) ORDER BY spm.StockPriceId) AS LatestPrice,
((SELECT TOP 1 spm.StockPrice FROM dbo.StockPrices spm WITH(NOLOCK) WHERE (spm.StockId = sp.StockId) AND (spm.StockDate = DATEADD(YEAR, -3, sp.StockDate)) ORDER BY spm.StockPriceId) - sp.StockPrice) AS PL,
CASE WHEN sp.StockPrice < (SELECT MIN(spm.StockPrice) FROM dbo.StockPrices spm WITH(NOLOCK) WHERE (spm.StockId = sp.StockId) AND (spm.StockDate BETWEEN DATEADD(YEAR, -3, sp.StockDate) AND DATEADD(DAY, -1, sp.StockDate))) THEN 'Opportunity' ELSE 'None' END AS [Status]
FROM dbo.StockPrices sp WITH(NOLOCK)
INNER JOIN dbo.Stocks s WITH(NOLOCK)
ON s.StockId = sp.StockId
INNER JOIN dbo.Exchanges e WITH(NOLOCK)
ON e.ExchangeId = s.ExchangeId
GO
我如何重写这个查询以提高效率?例如,使用WITH
关键字或其他一些我可能不知道的特性。
1条答案
按热度按时间bvjxkvbb1#
我将开始把你的5个子查询移到一个查询中,在4个
TOP (1)
查询中,除了一个查询外,所有查询都是按StockPriceId
排序的,所以我假设YearTPrice
(当前返回任意行)也是如此。对于
MIN
值,我使用窗口化的MIN
。我还删除了
NOLOCK
提示,因为它们显然被滥用了。如果您“msut”(您不需要)需要针对查询中的 * 每个表 * 使用NOLOCK
提示,那么请更改事务的隔离级别。当然,这些都是完全未经测试的,因为不存在样本数据,所以我无法知道这会对查询产生多大的影响(甚至影响结果,因为我无法测试),但它确实将5或6次
StockPrices
扫描减少到了1或2次