我有一个名为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的总和是&lt; = sum(total)* x
因此总和101和102 = 150和总和(总)* x = 160(例如)
我如何做我需要的或如何编辑此代码,以便它能够满足我的需求。
答案 0 :(得分: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
;
第一个CTE,grouped_and_ranked
检索有效销售额,并按票证计算总计以及总计(使用windowed SUM()
)。它还会在计算运行总计时将排名编号分配给稍后使用的故障单。
下一个CTE cumulative
是一个递归CTE。只要运行总计不超过总计的指定@percent
'年龄,它就会从前一个结果集中检索行。
主SELECT使用最终的故障单列表来获取详细信息行,方法是将列表连接回sales
表。
可以测试此查询at SQL Fiddle。
答案 1 :(得分:1)
仅使用窗口函数就可以相对轻松地完成此操作,而无需递归。
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。