【问题标题】:SQL Server 2016: Group by while updating the recordsSQL Server 2016:在更新记录时分组
【发布时间】:2020-06-08 15:05:07
【问题描述】:

我有一个场景,我需要根据产品确定每个客户/业务组合的保证金类型 - 这意味着客户/业务组合的利润率最高的产品应标识为“高”保证金类型。具有相同组合的所有其他产品应标识为低。所以,我需要一个 SQL 来相应地更新 MARGIN_TYPE 列。

我尝试做这样的事情,但不明白如何按客户/业务组合对其进行分组。任何帮助将不胜感激。谢谢!

UPDATE ORDER_TABLE
SET MARGIN_TYPE = 'High'
where MARGIN = (SELECT MARGIN FROM (SELECT MAX(MARGIN) FROM ORDER_TABLE) AS 
MARGIN) 

【问题讨论】:

    标签: sql sql-server tsql sql-update window-functions


    【解决方案1】:

    认为你只想要一个可更新的 CTE:

    WITH CTE AS(
        SELECT Customer,
               Margin,
               MarginType,
               MAX(Margin) OVER (PARTITION BY Customer) AS MaxMargin
        FROM dbo.YOurTable)
    UPDATE CTE
    SET MarginType = CASE Margin WHEN MaxMargin THEN 'High' ELSE 'Low' END;
    

    【讨论】:

    • 感谢您的回答。我认为这也不会按业务分组。会吗?
    • 然后将Business 添加到PARTITION BY, @Newbie 。我是基于我们拥有的(非常)小的样本集,其中CustomerBusiness 同时发生变化。
    • 感谢@Larnu。 CASE 语句似乎有一些问题,我不明白 Margin WHEN MaxMargin 是什么意思。
    • @Newbie the CASE expression (Case (Switch) statements don't exist in T-SQL) 是完全有效的......而且确实如此“罐头上写着什么”。当 Margin 的值为 MaxMargin 时,返回 High 否则返回 LowCASE 表达式是语言的基本部分。如果您提供可消耗的样本数据(不是图像),我很乐意测试上述内容/提供小提琴。但是,您不应该期望用户转录您的数据(这可能就是您投反对票的原因)。
    • 现在试试吧,@Newbie。该错误将真正与示例数据一起提供帮助...该错误与CASE表达式无关。
    【解决方案2】:

    使用更新包 CTE:

    WITH cte AS (
      SELECT *, ROW_NUMBER() OVER (PARTITION BY CUSTOMER, BUSINESS ORDER BY MARGIN DESC) rn
      FROM ORDER_TABLE
    )
    UPDATE cte
    SET MARGIN_TYPE = CASE WHEN rn = 1 THEN 'High' ELSE 'Low' END
    

    【讨论】:

      【解决方案3】:

      请使用以下查询,

      merge into ORDER_TABLE  OT
      using (select customer, business, product, margin, case when rnk = 1 then 'High' else 
      'Low' end as MARGIN_TYPE
      select customer, business, product, margin, row_number() over (partition by customer, 
      business, product, margin order by margin desc) as rnk
      from ORDER_TABLE
      group by) QRY
      on (OT.customer = QRY.customer and OT.business = QRY.business and OT.margin = 
      QRY.margin)
      when matched then
      update
      set 
      OT.MARGIN_TYPE = QRY.MARGIN_TYPE;
      

      【讨论】:

      • 。 . merge 对于 OP 想要做的事情来说太过分了。我建议你看看拉努的回答。
      【解决方案4】:
      UPDATE ORD
      SET MARGIN_TYPE = case ORD.margin = m.margin then 'high' else 'low' end
      from ORDER_TABLE ORD
      left outer join 
             (SELECT customer,business,MAX(MARGIN) MARGIN 
              FROM ORDER_TABLE 
              group by customer,business) m
      on(ORD.customer = m.customer and ORD.business = m.business)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多