简化对月份 12 列的 SQL 表的查询
我有一个正在生产的表,每个月有 12 列。我需要创建一个 SP,在其中传递产品 ID、客户和月份参数并检索该月的总和。
目前我的逻辑是
if month = 1 then
select sum(JAN) from table where productID = @id and customer = @cust
if month = 2 then
select SUM(FEB) from table where productID = @id and customer = @cust
....
查询有点复杂,但这是它的核心。有什么办法可以绕过这些“IF”语句吗?
编辑 - 这是一个 SQL Server 2000 数据库,但将迁移到 SQL Server 2005,当我迁移到 SQL Server 2005 时,PIVOT 和 UNPIVOT 将派上用场。
I have a table in production with 12 columns for each month. I need to create a SP where I pass in a productID, Customer and Month parameter and retrieve the sum of that month.
currently my logic is
if month = 1 then
select sum(JAN) from table where productID = @id and customer = @cust
if month = 2 then
select SUM(FEB) from table where productID = @id and customer = @cust
....
The query is a bit more involved but this is the core of it. Is there any way around these "IF" statements?
Edit - This is an SQL Server 2000 database but will be migrated to SQL Server 2005, the PIVOT and UNPIVOT will come in handy when I move to SQL Server 2005.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我认为查询的困难源于您的数据库未正确规范化这一事实。
您似乎有一个包含列的表:
要么是这样,要么是在存储过程中您创建了一个看起来像这样的临时表。这不是在 SQL 中执行此操作的最佳方法。您的目标应该是这样的表结构:
然后您可以使用简单的 WHERE 子句编写查询:
您可能还想检查查询中的年份,否则您可能会汇总 2009 年 1 月和 2010 年 1 月的数据。或者...也许您每年也有一张桌子? (我希望不会!)
注意:当然,此时更改表结构实际上可能并不可行。我仍然认为,如果您不知道这个问题,这一点值得一提。至少了解这一点可以防止将来再次犯同样的错误。
I think the difficulty in making the query stems from the fact that your database is not normalized correctly.
You appear to have a table with columns:
Either that or further up in the stored procedure you have created a temporary table that looks like that. This isn't the best way to do it in SQL. You should aim to have something like this as your table structure:
Then you can write your query using a simple WHERE clause:
You might also want to check the year in your query otherwise you could be summing data from January 2009 and January 2010. Or... maybe you have a table for each year too? (I hope not!)
Note: Of course, it may not actually be feasible for you to change the table structure at this point. I still felt that this is worth mentioning in case you were not aware of this issue. At least knowing about this may prevent the same mistake being made again in the future.
看看
UNPIVOT
- 您将取消透视以使列变为行,然后使用WHERE
子句仅获取您感兴趣的月份的行。内部:
然后连接到表以将月份转换为数字:
1月1日
2月2日
等。
然后
WHERE MonthNum = @param
Have a look at
UNPIVOT
- you would unpivot to make the columns into rows and then use aWHERE
clause to get only the rows for the month you are interested in.Inside:
Then join to a table to translate month to number:
JAN 1
FEB 2
etd.
Then
WHERE MonthNum = @param
假设您声明并初始化了变量,这应该可以工作。当然,如果您想要执行多个月的操作,情况会更复杂,这就是该设计不是最适合查询的原因之一。
Assuming you declare and inialize the variables, this should work. It's more complicated of course if you wan to do multiple months, that's one reason why the design is not the best for querying.
怎么样:
How about:
首先想到的是 - 您可以使用动态 sql 生成查询并使用简单的
EXEC
执行。在我看来,这听起来像是一个没有麻烦的解决方案,对于如此简单的查询,我认为没有理由不选择最简单的选项。
First thing that comes to mind - you could use dynamic sql to generate the query and and execute with a simple
EXEC
.This sounds to me like a no hassle solution and for a such a simple query I don't see a reason not to go with the easiest option.
您可以查看 SQL Server 中的 UNPIVOT 函数 - UnPivot
You could look at the UNPIVOT function in SQL Server - UnPivot