提高具有相关日期范围的联接表的查询性能

时间:2013-10-26 01:13:14

标签: sql database performance

信息


我需要一些帮助来找出查询一组表的最佳方法。需要找到两个互连表中可获得数据的最小和最大月份。有问题的表格和列如下所述:

股票

stock_id | region_id

地区

region_id | region_name

StockReturns

stock_id | month | return

RegionReturns

region_id | return_type_id | month | return

返回类型

return_type_id | return_type_name

问题


我已在SQL Fiddle

为此创建了一个沙箱

我想回答的问题是:对于给定的开始和结束月份(190001,201310),股票(VTI)及其相应区域的最早和最新回报数据是什么( 1)?此数据将用于根据日期范围进一步查询具有正确开始和结束月份的其他表。

我当前的查询(如下所述)开始在执行时间方面逐渐增加,因为这是在大多数网页加载时运行的主要查询,我关注性能。

关于数据,架构不是一成不变的,如果更适合这些类型的查询,可以更改架构。此外,ReturnType的构建方式与EAV类似,但它具有有限的选项限制(生产表中为5)。 StockReturns表目前有超过100,000行,并且上限为200万条记录。 RegionReturns表有3000行,上限为5000.

目前我正在查询类似的内容:

SELECT s.stock_id
    ,MIN(sr.month) AS start_month
    ,MAX(sr.month) AS end_month
FROM StockReturns sr
INNER JOIN Stocks s ON sr.stock_id = s.stock_id AND s.stock_id = 'VTI'
INNER JOIN Regions r ON s.region_id = r.region_id
INNER JOIN RegionReturns rf  ON s.region_id = rf.region_id
  AND rf.return_type_id = 1
  AND sr.month = rf.month
INNER JOIN RegionReturns mkt ON s.region_id = mkt.region_id
  AND mkt.return_type_id = 2
  AND sr.month = mkt.month
WHERE sr.month BETWEEN 190001 AND 201310
GROUP BY s.stock_id

本案的答案应该是:

stock_id | start_month | end_month
--------- ------------- ----------
VTI      | 201301      | 201302

1 个答案:

答案 0 :(得分:0)

您可以使用Regions表取消连接,因为如果需要区域名称,则只能加入该表。由于您只是检查股票区域是否存在两种返回类型,因此您也可以使用exists子句。

尝试这个怎么样?

SELECT sr.stock_id, 
       MIN(sr.month) AS start_month, 
       MAX(sr.month) AS end_month

FROM   StockReturns sr,
       Stocks s

WHERE  sr.stock_id = s.stock_id
AND    s.stock_id = 'VTI'
AND    sr.month BETWEEN 190001 AND 201310
AND    EXISTS (SELECT 1 
               FROM   RegionReturns rr
               WHERE  rr.region_id = s.region_id
               AND    rr.return_type_id = 1
               AND    rr.month = sr.month)
AND    EXISTS (SELECT 1 
               FROM   RegionReturns rr
               WHERE  rr.region_id = s.region_id
               AND    rr.return_type_id = 2
               AND    rr.month = sr.month)

GROUP BY sr.stock_id