【问题标题】:Need help converting an excel if and sumif formula to my SQL Server code需要帮助将 Excel if 和 sumif 公式转换为我的 SQL Server 代码
【发布时间】:2019-05-03 19:37:06
【问题描述】:

我选择了 SQL 查询,该查询返回我指定的列中的数据(客户、产品、月份、上一年度、当前年度、差异),我将其导出到 Excel 表。

在 Excel 中,我使用 If 和 Sumifs 公式向表 (Move) 添加了一列,该公式根据其他列中的条件返回是或否。

我相信 case when 相当于 SQL Server 中的 if,但我不知道如何按行处理 case。

基本上,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"
        )
    )
)

生成所附图片前 6 列的 SQL:

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 中发生的计算。因此,在 SQL 中创建我在 Excel 中创建的列,并在 SQL 中执行 Excel ifs。

我希望我足够清楚地解释我的请求和预期结果,但如果我需要澄清,请告诉我。谢谢

【问题讨论】:

  • 恐怕我们不能将您的图像用作数据,所以这使得它变得更加困难。 Excel 工作表和 SQL Server 表是完全不同的,因此如果不将表想象成工作表,那么您实际上需要做的第一件事。就个人而言,我认为您最好向我们展示您的示例数据是什么样子(格式为text 或 DDL 和 DML 语句),然后向我们展示您所追求的结果。在这里告诉我们您的 Excel 表达式可能只是一种干扰,因为语法非常不同。

标签: sql-server


【解决方案1】:

所以,我想我看到了你的一般逻辑。不过需要澄清一点:一个人“从一种产品转移到另一种产品”并没有太多,这对我来说意味着他们现在有了全新的偏好。相反,它更像是一个人已经“远离当前产品”而支持另一个人。尽管要注意真正捕捉到这一点的最佳方法是采用支出比例的方差,而不是绝对方差。除此之外,这就是我的处理方式:

如果可以的话,我更喜欢使用公用表表达式 (CTE),而不是子查询。在这种情况下,我将逻辑分为三层。

  • 在第一个 CTE(我称之为“baseData”)中,我将数据保持为未分类并执行 那里的工会。实际年份无关紧要,所以我转换为 描述性字符串而不是数字。记住我在做 这是为了可读性和风格,而不是出于性能原因。那么你 可能不得不使用它。主要是,我建议你绕过 您的“storedFunction1”并直接点击基础表。但 那是你的代名词。

  • 在称为“getVariances”的第二个 CTE 中,我计算方差 上一年度和本年度之间。请注意,当没有条件 匹配 case 语句,返回 null。所以聚合在 该区域仅分别将“当前”和“上一个”年份相加。

  • 在最后的 sql 语句中,我计算了“移动”。看窗户 满足您的需求的功能。基本上,它不需要聚合 压缩数据集,这是您在这里需要的,也是我需要的 相信等同于您尝试对 sumif 执行的操作。

代码如下:

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

【讨论】:

  • 你给了@pwilcox 很好的答案和方向我真的很感激。所以我拿了你的代码并修改了它,现在有一个新问题。我想我应该把它贴在这里,因为它仍然以某种方式与此相关,或者它是一个新问题?欢迎所有 cmets。
  • 一般你会发布一个新问题。如果它对用户有帮助,请从新的问题中添加指向此问题的链接。此外,为您面临的问题创建一个最小的可重现工作示例。我并不是说您可以简化上面的工作。但是,在你能解决新问题的范围内,你会得到更多的人来帮助你。祝你好运,如果你想让我看一下,请将我的名字放在你的新问题下的评论中。祝你好运。
  • @pwilcox,我认为您不能引用未在页面上进行过交互的人,因此当此处的 OP 向您发表评论时,它可能没有通知您。但这是他的new question
  • 不知道。谢谢@EricBrandt。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多