如何解决SQL 中的循环或递归还是使用 Python?
假设我有下表:
A | B | C | D |
---|---|---|---|
10 | 14 | 15 | 16 |
9 | 13 | 14 | 14 |
8 | 12 | 13 | 12 |
7 | 9 | 12 | 10 |
6 | 8 | 11 | 8 |
5 | 8 | 10 | 6 |
这里的 A-B-C-D 是购物车。我想购买购物车中的商品。商品的价格在每一行中。例如,购物车 A 有 6 个商品,其价格为 (10,9,8,7,6,5)。
如果另一个购物车中没有更便宜的商品,我只想购买给定购物车中的商品,否则我想从另一个购物车中购买该商品。当我购买每件商品时,我会将其标记为已购买。此外,每个购物车都有不同的购买能力。对于 A,我最多可以购买 5 个,对于 B 来说是 6 个,对于 C 来说是 4 个,对于 D 来说是 1 个。
购物车 A 是锚点,所以如果 A 达到容量,我们就会停下来。
事情就是这样。
购买:
- 来自 A 的 5 个
- 来自 A 的 6 个
- 这次购买后,来自 D - D 的 6 个达到容量
- 来自 A 的 7 个
- 来自 A 的 8 个
- 来自 B 的 8 个
- 来自 B 的 8 个
- A 中的 9 - A 达到容量
既然A达到了它的容量,它就会在这里结束。
您将如何在 SQL 中执行此操作。我想我可以使用循环,但我已经读过 SQL 是基于设置的以提高效率。我正在尝试做的似乎需要循环或递归。这是正确的方法吗,我应该为此使用 Python 吗?
感谢您的帮助!
解决方法
如果我理解正确,您可以通过逆透视、枚举行和过滤轻松完成此操作:
select t.*
from (select cart,val,row_number() over partition by cart order by val) as seqnum
from ((select 'A' as cart,A as val from t) union all
(select 'B' as cart,B from t) union all
(select 'C' as cart,C from t) union all
(select 'D' as cart,D from t)
) t
) t
where (cart = 'A' and seqnum <= 5) or
(cart = 'A' and seqnum <= 6) or
(cart = 'A' and seqnum <= 4) or
(cart = 'A' and seqnum <= 1)
order by val,cart;
注意:根据您使用的数据库,可能有更简单的逆透视方法。
,这应该有效:
with tab as (
select 'A' as cart,A as value from table
union
select 'B',B from table
union
select 'C',C from table
union
select 'D',D from table
)
select * from (
select tab.*,case
when
sum(case when cart = 'A' then 1 else 0 end) over(order by value) < 5
or sum(case when cart = 'A' then 1 else 0 end) over(order by value) = 5 and cart = 'A'
then 1
else 0
end as selected
from tab
) items
where items.selected = 1
,
如果您正在寻找 Python 解决方案,您可以使用 while
循环:
from collections import deque
full_data = [{'a': 10,'b': 14,'c': 15,'d': 16},{'a': 9,'b': 13,'c': 14,'d': 14},{'a': 8,'b': 12,'c': 13,'d': 12},{'a': 7,'b': 9,'c': 12,'d': 10},{'a': 6,'b': 8,'c': 11,'d': 8},{'a': 5,'c': 10,'d': 6}]
data = {i:deque(sorted([j[i] for j in full_data])) for i in ['a','b','c','d']}
s,m = [],{'a':5,'b':6,'c':4,'d':1}
while m['a']:
a,_,_ = min([(a,b[0],i) for i,[a,b] in enumerate(data.items()) if m[a]],key=lambda x:(x[1],x[-1]))
s.append((a,data[a].popleft()))
m[a] -= 1
输出:
[('a',5),('a',6),('d',7),8),('b',9)]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。