我得到了非常宽的月度索引表,如:
index_id | ... | Mar2009 | Apr2009 | May2009 | ... | Feb2010 | 1 | ... | value1 | value2 | value3 | ... | value11 |
有180列,名称分别代表月份和年份(2009年3月,2009年4月,...),大约有5000条记录,此表每月更新。
我还有第二个表格,其中包含以下数据:
index | some other data | index_id | saledate | saleprice | estimated price | 1234 | other data ... | 1 | 03/05/09 | 100 | ??????????????? |
(大约1百万条记录)我需要根据包括estimated_price
在内的索引发送完整记录,计算结果如下:
saleprice * ( value1 / value11 )
value1因为saledate id在2009年3月,因为当前月份值为11。
我有2个选项,都需要根据值访问特定列,第二个可以解决:
飞行计算(我如何根据saledate和当前数据访问索引表中的正确列) - 请注意数据表很大而且索引也不是小的
当更新索引表运行作业以计算估计价格时,将其置于数据表中,如何与上述问题相同(如何根据saledate访问索引表中的正确列)
第一个解决方案看起来效果看起来更有效,但我担心更新过程可能需要太长时间...我认为一个停滞不前的表会将宽索引表转换为长表,如:
index_id | date_from_column | index_value |
这种方式可以更容易合并表,但是我需要在更新索引表后使用TRUNCATE长表并运行180个INSERT,如:
INSERT INTO long_table SELECT index_id, 'Mar2009' AS date_from_column, Mar2009 AS index_value FROM indexes_table
其中每个下一个INSERT将具有下一个列名称形式索引
答案 0 :(得分:3)
从根本上说,你遇到的问题是你的设计没有规范化,结果是提取信息的查询更加困难。具体来说,第一个表的结构应为:
Create Table MonthlyIndexes As
(
index_id int not null
, date datetime not null
, value ...
, Primary Key ( index_id, date )
, Constraint CK_MonthlyIndexes_Date Check ( DatePart(d, date) = 1 )
)
index_id | date | value -------- -------- ------- 1 | 20090301 | ... 1 | 20090401 | ... ...
现在,检索所需信息的查询变得更加简单:
Select S.saleprice * ( MStart.value / MEnd.value )
From Sales As S
Join MonthlyIndexes As MStart
On MStart.date = DateAdd(d, -DatePart(d, S.saledate) + 1)
Join MonthlyIndexes As MEnd
On MEnd.date = DateAdd(d, -DatePart(d, CURRENT_TIMESTAMP) + 1)
除非重构您的架构,否则您可以像这样模拟正确的设计(假设SQL Server 2005 +):
With Indexes As
(
Select index_id, Cast('20090301' As datetime) as date, Mar2009
From MonthlyIndexes
Union All
Select index_id, Cast('20090401' As datetime) as date, Apr2009
From MonthlyIndexes
....
Union All
Select index_id, Cast('20100201' As datetime) as date, Feb2010
From MonthlyIndexes
)
Select S.saleprice * ( MStart.value / MEnd.value )
From Sales As S
Join MonthlyIndexes As MStart
On MStart.date = DateAdd(d, -DatePart(d, S.saledate) + 1)
Join MonthlyIndexes As MEnd
On MEnd.date = DateAdd(d, -DatePart(d, CURRENT_TIMESTAMP) + 1)
如果月度索引表很大,您可以对规范化表进行期间更新,并将其用于查询。
另一种解决方案是使用类似于CTE中的Union All查询的查询定期更新临时表,其中数据结构正确。如果数据每月添加一次,您甚至可以添加一个计划存储过程,检查是否存在给定月份的列并附加该月份的数据。这将涉及我通常建议反对的动态SQL,但是对于维护解决方案,它可能会解决问题(直到你说服管理层纠正架构)。