Нужна помощь в преобразовании формулы Excel if и sumif в мой код SQL Server - PullRequest
0 голосов
/ 03 мая 2019

Я выбрал SQL-запрос, который возвращает данные в указанных мной столбцах (Customer, Product, Mnth, Previous Yr, Current Yr, Variance), которые я экспортирую в таблицу Excel.

В Excel я добавил в таблицу столбец (Переместить) с формулами If и Sumifs, которые возвращают да или нет на основе критериев в других столбцах.

Я считаю, что тот случай, когда это эквивалентно if в SQL Server, но я не могу понять, как сделать случай, когда по строке.

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

См. Код Excel и SQL ниже и снимок экрана с результатами в Excel.

Версия Excel с отступом:

=IF(
    [@Product]="Product 1",
    IF(
        AND(
            [@Variance]<0,
            OR(
                SUMIFS([Variance],[Customer],[@Customer],[mnth],[@mnth],[Product],"Product 2")>0,
                SUMIFS([Variance],[Customer],[@Customer],[mnth],[@mnth],[Product],"Product 3")>0
            )
        ),
        "Yes",
        "No"
    ),
    IF(
        [@Product]="Product 2",
        IF(
            AND(
                [@Variance]<0,
                SUMIFS([Variance],[Customer],[@Customer],[mnth],[@mnth],[Product],"Product 3")>0
            ),
            "Yes",
            "No"
        ),
        IF(
            AND(
                [@Variance]>0,
                OR(
                   SUMIFS([Variance],[Customer],[@Customer],[mnth],[@mnth],[Product],"Product 2")<0,
                   SUMIFS([Variance],[Customer],[@Customer],[mnth],[@mnth],[Product],"Product 1")<0
                )
            ),
            "Yes",
            "No"
        )
    )
)

SQL, который производит первые 6 столбцов прикрепленной картинки:

SELECT
    subqry.Customer, subqry.Product, subqry.Mnth, 
    SUM(subqry.PriorYr) AS Previous Yr, 
    SUM(subqry.CurrentYr) AS Current Yr, 
    SUM(subqry.CurrentYr) - SUM(subqry.PriorYr) AS Variance
FROM
    (SELECT
         Customer, Product, 
         YEAR(TransactionDate) AS Yr, MONTH(TransactionDate) AS Mnth, 
         0 AS PriorYr, 
         SUM(TransactionCharges + OtherCharges) AS CurrentYr
     FROM
         Storedfunction1 ('01-01-19','03-31-19')
     WHERE
         Customer <> 'internal'   --EXCLUDE INTERNAL CUSTOMERS
         AND Product IN ('Product 1', 'Product 2', 'Product 3')
     GROUP BY
         Customer, Product, YEAR(TransactionDate), MONTH(TransactionDate)

     UNION ALL

     SELECT
         Customer, Product, 
         YEAR(TransactionDate) AS Yr, MONTH(TransactionDate) AS Mnth, 
         SUM(TransationCharges + OtherCharges) AS PriorYr, 
         0 AS CurrentYr
     FROM
         Storedfunction1 ('01-01-18','03-31-18')
     WHERE
         Customer <> 'internal'   --EXCLUDE INTERNAL CUSTOMERS
         AND Product IN ('Product 1', 'Product 2', 'Product 3')
     GROUP BY
         Customer, Product, YEAR(TransactionDate), MONTH(TransactionDate)
    ) Subqry
GROUP BY
    subqry.Customer, subqry.Product, subqry.Mnth
ORDER BY 
    1, 2, 3

Я хотел бы создать 7-й столбец (Переместить) и выполнить вычисления в SQL, а не в Excel, потому что я хочу ограничить вычисления, которые происходят в Excel. Поэтому создайте столбец, который я создаю в Excel в SQL, и выполните также Excel в SQL.

Надеюсь, я достаточно четко объясняю свой запрос и ожидаемые результаты, но дайте мне знать, если мне нужно уточнить. Спасибо

Excel_Result_Table

1 Ответ

0 голосов
/ 04 мая 2019

Итак, я думаю, что вижу вашу общую логику. Небольшое пояснение: не так уж много, что человек «перешел с одного продукта на другой», что для меня означает, что у него теперь совершенно новые предпочтения. Скорее, это больше похоже на то, как человек «отошел от текущего продукта» в пользу другого. Хотя остерегайтесь того, что по-настоящему захватить это лучше всего, принимая отклонение от пропорции потраченных денег, а не абсолютное отклонение. Кроме того, вот как я подошел к этому:

Вместо подзапросов я предпочитаю работать с общими табличными выражениями (CTE), если могу. В этом случае я разделил логику на три уровня.

  • В первом CTE, который я называю «baseData», я сохраняю данные неагрегированными и выполняю союз там. Фактический год не имеет значения, поэтому я перешел в описательная строка вместо числа. Имейте в виду, что я делаю это для удобства чтения и стиля, а не для повышения производительности. Так что вы возможно, придется работать с этим. В основном, я советую вам обойти ваш 'сохраненная функция1' и попал в базовую таблицу напрямую. Но это твоя родословная.

  • Во втором CTE, называемом «getVariances», я вычисляю дисперсию между предыдущим и текущим годом. Обратите внимание, что когда нет условий совпадает с оператором case, возвращается ноль. Таким образом, агрегации в эта область складывается только из 'cur' и 'prev' лет соответственно.

  • В последнем выражении sql я вычисляю 'move'. Заглянуть в окно функции для ваших нужд. В основном, это занимает агрегацию без сжатие набора данных, что вам нужно здесь и что я вера эквивалентна тому, что вы пытаетесь сделать со своими суфифами.

Вот код:

with

    baseData as (

        select 'prev' as yr, Customer, Product, TransactionDate, TransactionCharges, OtherCharges
        from Storedfunction1 ('01-01-19','03-31-19')

        union all
        select 'cur' as yr, Customer, Product, TransactionDate, TransactionCharges, OtherCharges
        from Storedfunction1 ('01-01-18','03-31-18')

    ),

    getVariances (

        select      Customer, Product, mnth,

                    variance = 
                          sum(case when yr = 'cur' then transactionCharges + otherCharges end)
                        - sum(case when yr = 'prev' then transactionCharges + otherCharges end)

        from        baseData
        cross apply (select mnth = month(transactionDate)) ap
        where       Customer <> 'internal'   
        and         Product in ('Product 1', 'Product 2', 'Product 3')
        group by    Customer, Product, mnth

    )

    select      *,

                move = 
                    case 
                    when variance >= 0 then 'no' 
                    when max(variance) over(partition by customer, mnth) > 0 then 'yes'
                    else 'no'
                    end

    from        getVariances
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...