【问题标题】:Simpilify query for SQL table with 12 columns for month简化对月 12 列 SQL 表的查询
【发布时间】:2010-01-29 20:13:13
【问题描述】:

我有一个生产表,每个月有 12 列。我需要创建一个 SP,在其中传入 productID、Customer 和 Month 参数并检索该月的总和。

目前我的逻辑是

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 将派上用场。

【问题讨论】:

  • 答案都非常好。谢谢

标签: sql sql-server sql-server-2000


【解决方案1】:

我认为进行查询的困难源于您的数据库未正确规范化。

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

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 月的数据。或者...也许您也有每年的表格? (希望不会!)


注意:当然,此时更改表结构可能实际上并不可行。我仍然觉得这值得一提,以防你不知道这个问题。至少知道这一点可以防止将来再次犯同样的错误。

【讨论】:

  • 我同意,但我的选择有限。这是一个将升级的旧系统。
  • 那么你需要 Cade Roux 的解决方案。
  • 这是 SQL Server 2000,所以 UNPIVOT 不走运。我编辑了帖子以指示数据库服务器版本。
【解决方案2】:

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

内部:

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

然后加入表格以将月份转换为数字: 1月1日 2月2日 等等。

然后WHERE MonthNum = @param

【讨论】:

  • 我还建议使用 UNPIVOT 创建一个 VIEW,以便您可以正确进行查询。
  • 假设表结构不能更改,这看起来是解决这种情况的一个很好的实用解决方案。但是我认为您的查询中可能存在语法错误。
  • @MarkByers 抱歉,我懒得模拟一张桌子和整个样本。因此,伪代码
  • @TravisG - 当然,我们在这两种方式中都使用了很多视图。要旋转/展平的视图和要取消旋转/规范化的视图。我还完成了代码生成来生成数据或架构可以更改的 PIVOTS/UNPIVOT。
【解决方案3】:
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 

假设您声明并初始化变量,这应该可以工作。当然,如果你想做多个月,那就更复杂了,这就是为什么设计不是最适合查询的原因之一。

【讨论】:

    【解决方案4】:

    怎么样:

    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
    

    【讨论】:

      【解决方案5】:

      首先想到 - 您可以使用动态 sql 生成查询并使用简单的EXEC 执行。

      对我来说,这听起来像是一个简单的解决方案,对于如此简单的查询,我认为没有理由不使用最简单的选项。

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:
          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'
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-07-09
            • 1970-01-01
            • 1970-01-01
            • 2018-09-12
            • 1970-01-01
            • 2021-11-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多