【问题标题】:Cumulative sum & percentage累计和百分比
【发布时间】:2012-07-23 19:33:57
【问题描述】:

我有一个名为 Sales 的表:

id_sale  id_ticket  total  state
-------  ---------  -----  -----
100      100        30     inactive    
101      101        30     active    
102      101        60     active    
103      102        30     active    
104      102        30     active    
105      103        10     active    
106      103        5      active    

我需要的是在状态处于活动状态时获取total 列的总和(总和)并将其乘以 x 百分比(我可以这样做),因此我必须选择所有票他们的总和(所有票的总和)是<= sum(total) * x percentage 并将其复制到另一个表(相同的值)

所以如果我有 101 票的总和 = 90 票的总和 102 票的总和 = 60 票的总和 103 票的总和 = 15,并且总和(总)*x 百分比 = 160,查询将只返回所有门票 101 和 102 的信息。

读了一上午,我发现了一个代码,它以某种方式完成了我需要的事情,但使用的是 id_Sales 而不是 id_ticket:

    select t1.id_sale, t1.total, SUM(t2.total) as sum
    from sales t1
    inner join sales t2 on t1.id_sale >= t2.id_sale
    where t2.state='active'
    group by t1.id_sale, t1.total
    having sum(t2.total)<=(
                           select sum(total)*.65
                           from sales
                           where state='active')
    order by t1.id_sale

我希望收到的是:

id_sale  id_ticket  total  state
-------  ---------  -----  ----- 
101      101        30     active    
102      101        60     active    
103      102        30     active    
104      102        30     active

其中 101 票和 102 票之和为

所以 101 和 102 之和 = 150 和 sum(total)*x = 160(例如)

我怎样才能做我需要的事情,或者我怎样才能编辑这段代码,让它做我正在寻找的事情。

【问题讨论】:

  • 感谢您发布示例数据,但您能否发布您需要的预期结果示例?
  • 我希望我可以 +10 @bluefeet 的评论。很高兴知道您尝试的查询,但我们大多数人更愿意知道您实际期望的结果。
  • 第二步的票单怎么选(这里要涨到160但不超过)票号asc?

标签: sql-server sql-server-2005 sum


【解决方案1】:

你可以这样开始:

WITH grouped_and_ranked AS (
  SELECT
    id_ticket,
    ticket_total = SUM(total),
    grand_total = SUM(SUM(total)) OVER (),
    ticket_rnk = ROW_NUMBER() OVER (ORDER BY id_ticket)
  FROM sales
  WHERE state = 'active'
  GROUP BY id_ticket
),
cumulative AS (
  SELECT
    id_ticket,
    ticket_total,
    grand_total,
    ticket_rnk,
    total_so_far = ticket_total
  FROM grouped_and_ranked
  WHERE ticket_rnk = 1
  UNION ALL
  SELECT
    r.id_ticket,
    r.ticket_total,
    r.grand_total,
    r.ticket_rnk,
    total_so_far = c.total_so_far + r.ticket_total 
  FROM grouped_and_ranked r
    INNER JOIN cumulative c ON r.ticket_rnk = c.ticket_rnk + 1
  WHERE r.ticket_total columns
)
SELECT
  s.id_sale,
  s.id_ticket,
  s.total,
  s.state
FROM sales s
INNER JOIN cumulative c ON s.id_ticket = c.id_ticket
;

第一个CTEgrouped_and_ranked 检索有效销售并按票证计算总计以及总计(使用windowedSUM())。它还会为门票分配排名编号,以便稍后在计算运行总数时使用。

下一个 CTE,cumulative,是一个递归 CTE。只要运行总计不大于总计的指定@percent'age,它就会从上一个结果集中检索行。

主 SELECT 使用最终工单列表获取详细信息行,方法是将列表连接回 sales 表。

这个查询可以测试at SQL Fiddle

【讨论】:

  • 感谢您的回答,它帮助我改进了我正在处理的代码。每次我学到新东西时:D
【解决方案2】:

这可以相对容易地仅使用窗口函数完成,无需递归。

select id_sale, id_ticket, total, state
from (
  select
    id_sale, id_ticket, total, state,

    -- Now we can calculate the cumulative percentage easily
    sum(sum_per_ticket) over (order by id_sale) / sum(sum_per_ticket) over () percentage
  from (
    select
      id_sale, id_ticket, total, state,

      -- Calculate the sum per ticket and place it only on the first row per id_ticket
      -- Fill the other rows with nulls.
      case when id_sale = 
                first_value(id_sale) over (partition by id_ticket order by id_sale) 
           then sum(total) over (partition by id_ticket) end sum_per_ticket
    from sales
    where state = 'active'
  ) t
) t
where percentage <= 0.65
order by id_sale

I have blogged about calculating cumulative percentages in more detail here.

【讨论】:

    猜你喜欢
    • 2014-01-24
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    • 2017-03-03
    • 2017-03-06
    • 2018-09-24
    相关资源
    最近更新 更多