简化对月份 12 列的 SQL 表的查询

发布于 2024-08-19 11:32:19 字数 445 浏览 7 评论 0原文

我有一个正在生产的表,每个月有 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 技术交流群。

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

发布评论

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

评论(7

囚我心虐我身 2024-08-26 11:32:19

我认为查询的困难源于您的数据库未正确规范化这一事实。

您似乎有一个包含列的表:

productId
customer
JAN
FEB
...

要么是这样,要么是在存储过程中您创建了一个看起来像这样的临时表。这不是在 SQL 中执行此操作的最佳方法。您的目标应该是这样的表结构:

productId
customer
date
amount

然后您可以使用简单的 WHERE 子句编写查询:

SELECT SUM(amount)
FROM table
WHERE MONTH(date) = month AND productID = @id and customer = @cust

您可能还想检查查询中的年份,否则您可能会汇总 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:

productId
customer
JAN
FEB
...

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:

productId
customer
date
amount

Then you can write your query using a simple WHERE clause:

SELECT SUM(amount)
FROM table
WHERE MONTH(date) = month AND productID = @id and customer = @cust

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.

韶华倾负 2024-08-26 11:32:19

看看 UNPIVOT - 您将取消透视以使列变为行,然后使用 WHERE 子句仅获取您感兴趣的月份的行。

内部:

SELECT *
FROM tbl UNPIVOT FOR Month IN ([JAN], [FEB], etc...)

然后连接到表以将月份转换为数字:
1月1日
2月2日
等。

然后WHERE MonthNum = @param

Have a look at UNPIVOT - you would unpivot to make the columns into rows and then use a WHERE clause to get only the rows for the month you are interested in.

Inside:

SELECT *
FROM tbl UNPIVOT FOR Month IN ([JAN], [FEB], etc...)

Then join to a table to translate month to number:
JAN 1
FEB 2
etd.

Then WHERE MonthNum = @param

雪落纷纷 2024-08-26 11:32:19
select sum(case when @month = 1 then Jan
        when @month = 2 then Feb
        when @month = 3 then Mar
        when @month = 4 then Apr
        when @month = 5 then May
        when @month = 6 then Jun
        when @month = 7 then Jul
        when @month = 8 then Aug
        when @month = 9 then Sep
        when @month = 10 then Oct
        when @month = 11 then Nov
        when @month = 12 then [Dec] end) 
        from mytable
        where productID = @id and customer = @cust 

假设您声明并初始化了变量,这应该可以工作。当然,如果您想要执行多个月的操作,情况会更复杂,这就是该设计不是最适合查询的原因之一。

select sum(case when @month = 1 then Jan
        when @month = 2 then Feb
        when @month = 3 then Mar
        when @month = 4 then Apr
        when @month = 5 then May
        when @month = 6 then Jun
        when @month = 7 then Jul
        when @month = 8 then Aug
        when @month = 9 then Sep
        when @month = 10 then Oct
        when @month = 11 then Nov
        when @month = 12 then [Dec] end) 
        from mytable
        where productID = @id and customer = @cust 

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.

ぃ弥猫深巷。 2024-08-26 11:32:19

怎么样:

declare @month int
set @month = 2
select sum(case @month
                when 1 then JAN
                when 2 then FEB
                when 3 then MAR
                when 4 then APR
                when 5 then MAY
                when 6 then JUN
                when 7 then JUL
                when 8 then AUG
                when 9 then SEP
                when 10 then OCT
                when 11 then NOV
                when 12 then DEC
                else 0
            end) 
from table 
where productID = @id 
and customer = @cust

How about:

declare @month int
set @month = 2
select sum(case @month
                when 1 then JAN
                when 2 then FEB
                when 3 then MAR
                when 4 then APR
                when 5 then MAY
                when 6 then JUN
                when 7 then JUL
                when 8 then AUG
                when 9 then SEP
                when 10 then OCT
                when 11 then NOV
                when 12 then DEC
                else 0
            end) 
from table 
where productID = @id 
and customer = @cust
粉红×色少女 2024-08-26 11:32:19

首先想到的是 - 您可以使用动态 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.

独闯女儿国 2024-08-26 11:32:19

您可以查看 SQL Server 中的 UNPIVOT 函数 - UnPivot

You could look at the UNPIVOT function in SQL Server - UnPivot

初熏 2024-08-26 11:32:19
select sum(quantity) from table unpivot (quantity for month in (jan,feb,mar/*etc*/)) as t where where productID = @id and customer = @cust and month='jan'
select sum(quantity) from table unpivot (quantity for month in (jan,feb,mar/*etc*/)) as t where where productID = @id and customer = @cust and month='jan'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文