找出求和值何时达到SQL中的某个检查点

时间:2015-11-26 13:58:46

标签: sql sql-server sum

首先:我在之前提出的问题中找到了我的问题的一些可能的答案,但我遇到了让它们正常工作的问题。我知道这个问题已经被问过,但答案总是工作代码,几乎没有解释所使用的方法。

所以:我必须找出客户何时达到VIP状态,即当他的订单价值超过5万时。我有2个表:一个有orderid,customerid和orderdate,第二个是orderid,数量和单价。 我写的查询结果应该是3个字符串宽,一个用customerid,一个用真/假命名"是VIP?",第三个是获得VIP的日期状态(与之前的订单相加的订单日期超过50 000) - 如果客户未达到VIP状态,则最后一个应为空白

select o.customerid, sum(od.quantity*od.unitprice),
case
when sum(od.quantity*od.unitprice)>50000 then 'VIP'
else 'Normal'
end as 'if vip'
from
orders o join [Order Details] od on od.orderid=o.orderid
group by o.customerid

就我所获得的代码而言,它返回了客户的状态,现在我需要获取发生的日期。

4 个答案:

答案 0 :(得分:3)

您可以使用窗口函数轻松计算运行总计:

select o.customerid, 
       o.orderdate, 
       sum(od.quantity*od.unitprice) over (partition by o.customerid order by orderdate) as running_sum, 
from orders o 
   join Order_Details od on od.orderid = o.orderid
order by customer_id, orderdate;

现在您需要找到一种方法来检测第一行,其中运行总计超过阈值:

一旦达到阈值,以下查询将开始以递减方式对行进行编号。这反过来意味着具有数字1的行是第一个越过阈值的行:

with totals as (
  select o.customerid, 
         o.orderdate, 
         sum(od.quantity*od.unitprice) over (partition by o.customerid order by orderdate) as running_sum, 
         case
           when 
              sum(od.quantity*od.unitprice) over (partition by o.customerid order by orderdate) > 50000 then row_number() over (partition by o.customerid order by orderdate desc)
           else 0
         end as rn
  from orders o 
     join Order_Details od on od.orderid = o.orderid
)
select *
from totals
where rn = 1
order by customerid;

SQLFiddle示例:http://sqlfiddle.com/#!6/a7f18/3

答案 1 :(得分:3)

使用分析函数SUM OVER获得累积和。然后添加聚合以查找最小日期:

with cte as
 ( select o.customerid, 
      o.orderdate, 
      case when sum(od.quantity*od.unitprice) -- running total
                over (partition by o.customerid
                      order by orderdate
                      rows unbounded preceding) > 50000 
           then 'Y' 
           else 'N' 
      end as VIP
  from orders o 
  join Order_Details od on od.orderid = o.orderid
 )
select customerid,
   MAX(VIP) AS "isVIP?",  -- either 'N' or 'Y'
   MIN(CASE WHEN VIP = 'Y' THEN orderdate END) AS VIP_date -- only when VIP status reached
from cte
group by customerid
order by customers;

请参阅fiddle

答案 2 :(得分:1)

不要用逻辑来复杂答案,以显示'vip'和'vip date'。这将为您提供每个客户订单的运行总计。

3.3.12

答案 3 :(得分:0)

要回答关于如何处理的问题,您可以考虑使用SQL触发器,该触发器在所涉及的表的每次更新时运行,并在达到阈值时设置状态。这将设置事件发生时的日期

另一种方法是使用存储过程,其中您可以对记录使用循环顶部迭代并到达日期。

可以根据数据量进行选择,前者适用于极大量的数据。