我无法以适合数据库的方式表示项目数据。为了提供帮助,我在以下示例中设置了一个SQL小提琴:http://sqlfiddle.com/#!2/6d01c2/14/0
最简单的说,我有三个表:Fund,FundReturn和FactorReturn。 Fund通过FundReturn获得了许多月度回报。基金也有一个地区(如美国或外国),这些地区有一个所谓的因子回归。因此,FactorReturn与基金的关系不是直接的,而是通过基金所属的区域。
**Fund**
fund_symbol | varchar(5) | PRI
region_key | varchar(255) |
**FundReturn**
fund_symbol | varchar(255) | PRI
return_month | int(10) | PRI
return_value | decimal(5,4) |
**FactorReturn**
region_key | varchar(255) | PRI
factor_key | varchar(255) | PRI
return_month | int(10) | PRI
return_value | decimal(5,4) |
目标是在特定时间段内提取基金的回报以及相应的因子回报以执行某些分析。最终的表示看起来像这样:
fund_symbol | month | fund_return | factor_ret_1 | factor_ret_2 | factor_ret_3
VTI | 201001 | 0.0100 | 0.0200 | -0.0100 | 0.0000
VTI | 201002 | 0.0500 | 0.0300 | 0.0300 | 0.0010
VTI | 201003 | 0.0300 | 0.0100 | -0.0200 | 0.0020
此外,我正在使用PHP Doctrine ORM并已映射数据,以便能够使用如下方法:
$fund = $em->find('VTI');
$fund->getFundReturns(); // Would return array with FundReturn objects.
$fund->getFactorReturns(); // Would return array with FactorReturn objects.
由于数据的性质,尝试在一个查询中查询基金回报和因子回报会以指数方式增加返回的行数。一旦我尝试在ORM中使用它,这会加剧,因为无法构建具有广泛日期范围的对象图。使用多个查询是我目前的解决方案,但是使用ORM时这很棘手,因为从我的代码中错误地访问关系会触发大量的SQL查询。
http://sqlfiddle.com/#!2/6d01c2/14/0处的查询显示查询12个月后如何返回432行。
所以我的问题是:
答案 0 :(得分:1)
首先假设任何解决方案无疑将最终使用'JOIN',我将生成所有外键整数值。这将使您的表关系更快,并且在存储和更新速度方面更经济。因此,例如,基金表将具有整数唯一ID(例如1)以及符号(自然密钥,例如VTI) 你可以在这里阅读更多: Surrogate vs. natural/business keys
此外,您可能正在沿着实体属性值路线走下去,这一点已经讨论过了。 Entity Attribute Value Database vs. strict Relational Model Ecommerce
此实体属性值模型查询很复杂,但可以让用户灵活地添加自己的因子返回键。
其次,如果沿着这条路走下去,你可能会在大多数ORM中努力查询。我会尝试手动构建查询,如下所示:
SELECT f.*
,fr.return_month AS fund_return_month
,fr.return_value AS fund_return
,hml.return_value AS hml
,mkt.return_value AS mkt
,smb.return_value as smb
FROM Fund f
INNER JOIN FundReturn fr ON f.fund_symbol = fr.fund_symbol
LEFT JOIN FactorReturn hml
ON f.region_key = hml.region_key
AND hml.factor_key = 'hml'
AND hml.return_month = fr.return_month
LEFT JOIN FactorReturn mkt
ON f.region_key = mkt.region_key
AND mkt.factor_key = 'mkt'
AND mkt.return_month = fr.return_month
LEFT JOIN FactorReturn smb
ON f.region_key = mkt.region_key
AND smb.factor_key = 'smb'
AND smb.return_month = fr.return_month
WHERE f.fund_symbol = 'VTI'
AND fr.return_month BETWEEN 201001 AND 201012
AND hml.return_month BETWEEN 201001 AND 201012;