SQL Server - 根据值搜索特定列

发布于 2024-10-17 00:20:59 字数 1167 浏览 1 评论 0原文

我得到了非常宽的每月索引表,如下所示:

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 | ??????????????? |

大约 100 万条记录),我需要根据索引提供完整记录,包括 estimated_price ,其计算方式为: saleprice * ( value1 / value11 ) value1 是因为销售日期 ID 是 2009 年 3 月,value11 是因为当前月份。

我有两个选项,两个选项都需要根据值访问特定列,第二个选项可以解决:

  1. 动态计算(以及如何根据销售日期和当前数据访问索引表中的正确列) - 请注意数据表很大,索引也不小

  2. 当更新索引表运行一个作业来计算估计价格时,将其放入数据表中,如何与上面相同的问题(如何访问基于索引表中的正确列销售日期

第二个解决方案乍一看似乎更有效,但是我担心更新过程可能需要太长时间...我考虑使用一个临时表将宽索引表转换为长表,例如:

index_id | date_from_column | index_value |

这样可以更容易合并表,但是我需要在更新索引表后截断长表并运行 180 个插入,例如:

INSERT INTO long_table SELECT index_id, 'Mar2009' AS date_from_column, Mar2009 AS index_value FROMindexs_table

其中每个下一个 INSERT 将具有下一列名称表单索引

I got very wide table of monthly indexes look like:

index_id | ... | Mar2009 | Apr2009 | May2009 | ... | Feb2010 |
1        | ... | value1  | value2  | value3  | ... | value11 |

There are 180 columns, names are in series what represent month and year (Mar2009, Apr2009, ...), and there are about 5000 records, this table is updated monthly.

I also got second table with data like:

index | some other data | index_id | saledate | saleprice | estimated price |
1234  | other data ...  |        1 | 03/05/09 |       100 | ??????????????? |

(about 1 milion records) and I need to delivered full record based on index including estimated_price which is calculated as:
saleprice * ( value1 / value11 ) value1 because saledate id in March 2009, value11 because of current month.

I got 2 options, both need to access specific column based on value, second can have work around:

  1. Calculate on fly ( andhow I can access correct column in indexes table based of saledate and current data) - be aware that data table is big and indexes are not samll either

  2. When update indexes table run a job to calculate estimated price place it in data table, how ever same question as above (how access correct column in indexes table based of saledate )

Second solution looks more effective at first look, however I afraid that that update process can take too long... I consider a stagging table that will convert wide index table to long table like:

index_id | date_from_column | index_value |

this way it could be easier to merge tables, however I will need to after update indexes table TRUNCATE long table and run 180 INSERTs like:

INSERT INTO long_table SELECT index_id, 'Mar2009' AS date_from_column, Mar2009 AS index_value FROM indexes_table

where each next INSERT will have next column name form indexes

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瑾夏年华 2024-10-24 00:20:59

从根本上来说,您遇到的问题是您的设计没有标准化,结果是提取信息的查询更加困难。具体来说,第一个表的结构应如下所示:

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,我通常建议不要使用动态 SQL,但是对于维护解决方案来说,它可能会解决问题(直到您说服管理层更正架构)。

Fundamentally, the problem you have is that your design is not normalized and the consequence is that the queries to extract information are more difficult. Specifically, the first table should be structured as:

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 | ...
...

Now the query to retrieve the information you want becomes simpler:

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)

Barring a restructing of your schema, you can simulate the proper design like so (assuming 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)

If the monthly indexes table is large, you could do period updates of a normalized table and use that for your query.

Another solution is to periodically update a staging table with the data structured properly using a query akin to the Union All query in my CTE. If the data is added once a month, you could even add a schedule stored proc that checks whether there is a column for a given month and appends that month's data. That would involve dynamic SQL which I'd normally recommend against however for a maintenance solution it might solve the problem (until you convince management to correct the schema).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文