Упростить запрос для таблицы SQL с 12 столбцами в месяц - PullRequest
1 голос
/ 29 января 2010

У меня есть производственная таблица с 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

....

Запрос немного сложнее, но это его ядро. Есть ли способ обойти эти заявления "ЕСЛИ"?

Редактировать - это база данных SQL Server 2000, но она будет перенесена в SQL Server 2005, PIVOT и UNPIVOT пригодятся при переходе на SQL Server 2005.

Ответы [ 7 ]

8 голосов
/ 29 января 2010

Я думаю, что сложность в создании запроса связана с тем, что ваша база данных не нормализована правильно.

Похоже, у вас есть таблица со столбцами:

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 г. и январь 2010 г. (Надеюсь нет!)


Примечание. Конечно, на самом деле изменение структуры таблицы на данном этапе может оказаться невозможным. Я все еще чувствовал, что это стоит упомянуть, если вы не знали об этой проблеме. По крайней мере, знание этого может предотвратить повторение той же ошибки в будущем.

6 голосов
/ 29 января 2010

Взгляните на UNPIVOT - вы бы не развернули столбцы в строки, а затем использовали предложение WHERE, чтобы получить только строки за интересующий вас месяц.

Внутри:

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

Затем присоединитесь к таблице, чтобы перевести месяц в число: 1 января 2 февраля ETD.

Тогда WHERE MonthNum = @param

3 голосов
/ 29 января 2010
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 

Если вы объявляете и инициализируете переменные, это должно работать. Конечно, это сложнее, если вы хотите сделать несколько месяцев, это одна из причин, почему дизайн не лучший для запросов.

3 голосов
/ 29 января 2010

Как насчет:

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
1 голос
/ 29 января 2010

Вы можете посмотреть на функцию UNPIVOT в SQL Server - UnPivot

1 голос
/ 29 января 2010

Первое, что приходит на ум - вы можете использовать динамический sql для генерации запроса и выполнить с простым EXEC.

Для меня это звучит как простое решение, и для такого простого запроса я не вижу причины не использовать самый простой вариант.

0 голосов
/ 29 января 2010
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'
...