的确很难,我的思路是做一个存储过程,
把输入的参数放在一个字符串中,如‘aaaa:1,aaaa:1,bbbb:1',
然后在存储过程中分拆到临时表中#tab(商品, 数量),然后查询select 套装代码
from 表A left join #tab on 表A.商品 = #tab.商品 and 表A.数量 = #tab.数量
group by 套装代码
having sum(case when #tab.商品 is null then 1 else 0 end) = 0
把输入的参数放在一个字符串中,如‘aaaa:1,aaaa:1,bbbb:1',
然后在存储过程中分拆到临时表中#tab(商品, 数量),然后查询select 套装代码
from 表A left join #tab on 表A.商品 = #tab.商品 and 表A.数量 = #tab.数量
group by 套装代码
having sum(case when #tab.商品 is null then 1 else 0 end) = 0
套装代码表:
代码 名称
0001 aaaa
0002 bbbb再建销售表代码 数量
0001 1
0002 2
0001 3
0002 2再关联查询,方便实用安全
declare @sales table(商品,数量)
/* 在此请自行导入销售商品明细,
例如:
insert @sales(商品,数量) select 商品编码,sum(数量) from 交易明细
group by 商品编码 where 发票号='AP1234567'
*/
declare @group table(row int identity,套装,商品,数量,primary key(套装,商品))
/* 在此请自行(重新)导入套装数据,
例如:
insert @group(套装,商品,数量) select 套装代码,商品,sum(数量)
from 表A group by 套装代码,商品
*/
declare @result table(套装)
declare @p int
set @p=1
while @p<=(select max(row) from @group)
begin
if not exists(select * from @sales as s full join @group as g
on a.商品=g.商品 where g.row=@p and (s.商品 isnull or s.数量<g.数量))
begin
insert @result(套装) select 套装 from @gropup where row=@p
update s set 数量=数量-g.数量
from @sales as s inner join @group as g on g.row=@p and s.商品=g.商品
end
else set @p=@p+1
end
--下面输出结果:
select 套装,count(*) as 套数 from @result group by 套装说明:full join那句,使用not exists的目的是剔除以下不符合“成套”的两种情况:
1. group中有的商品品种但是在sales中没有。
2. group中和sales种商品对应,但是sales中的商品数量不够组合进一套套装。一旦找到一套套装,则从sales中减去此一套套装的数量,然后继续看看此的套装是否还可以再匹配一套;否则,看看下一个套装是否成立。
Select 套装代码 where 商品 = 'aaa' and 数量 = 1
套装代码 char(4),
商品 varchar(4),
数量 int)insert A select '0001','aaaa',1
insert A select '0001','aaaa',1
insert A select '0001','bbbb',1
insert A select '0002','aaaa',1
insert A select '0002','cccc',1
insert A select '0002','dddd',1
insert A select '0002','eeee',2create table #t(
商品 varchar(4),
数量 int)insert #t select 'aaaa',1
insert #t select 'aaaa',1
insert #t select 'bbbb',1select distinct 套装代码 from A where 套装代码 not in
(select 套装代码 from A as B where not exists
(select * from #t where 商品 = B.商品 and 数量 = B.数量))
你的方法有问题,你试试这个:
insert #t select 'aaaa',1
insert #t select 'cccc',1
insert #t select 'bbbb',1
它也能把0001检索出来,这是不对的to:eminena
也就是多个商品组成一个套装商品
感谢大家的参与,另商品的顺序不确定
套装代码 char(4),
商品 varchar(4),
数量 int)insert A select '0001','aaaa',1
insert A select '0001','aaaa',1
insert A select '0001','bbbb',1
insert A select '0002','aaaa',1
insert A select '0002','cccc',1
insert A select '0002','dddd',1
insert A select '0002','eeee',2create table #t(
商品 varchar(4),
数量 int)insert #t select 'aaaa',1
insert #t select 'aaaa',1
insert #t select 'bbbb',1
select * from A
where
(select count(*) from A aa where aa.套装代码=a.套装代码)=(select count(*) from #t)
and
(select count(*) from (select distinct 套装代码,商品,数量 from A) aa where aa.套装代码=a.套装代码)=(select count(*) from (select 商品,数量 from A aa where aa.套装代码=a.套装代码 union select 商品,数量 from #t) tem)
0001 aaaa 1
0001 bbbb 1
为什么代码 0001 里有 两个一样的品名和数量商品: aaaa ?
select distinct 套装代码 from A as D where 套装代码 not in
(select 套装代码 from A as B where not exists
(select * from #t where 商品 = B.商品 and 数量 = B.数量))
and not exists
(select * from #t as C where not exists
(select * from A where 套装代码 = D.套装代码 and 商品 = C.商品 and 数量 = C.数量))
select distinct 套装代码 from A as D where 套装代码 not in
(select 套装代码 from A as B where not exists
(select * from #t where 商品 = B.商品 and 数量 = B.数量) or
(select count(*) from A where 套装代码 = B.套装代码 and 商品 = B.商品 and 数量 = B.数量) <>
(select count(*) from #t where 商品 = B.商品 and 数量 = B.数量))
and not exists
(select * from #t as C where not exists
(select * from A where 套装代码 = D.套装代码 and 商品 = C.商品 and 数量 = C.数量))
not exists
(select * from #t as C where not exists
(select * from A where 套装代码 = D.套装代码 and 商品 = C.商品 and 数量 = C.数量))
to: JGTM2000(铁马小子)
如果读起教科书来头头是道,解决起基本问题来连个“毛”都没有,错误百出,算是“守规矩、学得好”的话,那么也太“成事不足”了。我小时候听了一个笑话:有个小孩,他妈妈出门前给他烙了一张大饼,把饼套在他脖子上叫他饿了就吃。结果,三天后,他妈妈回来一看,他已经饿死了!原来他竟然傻到“只知道啃面前嘴巴够得着的一小块饼”!! 我想这个论坛上的人确实没几个想在天上开飞机的,但是想学以致用的不在少数。
create view SuiteView
as
select
SuiteID, ProductID, sum(Quantity) as Quantity
from
Suite
group by SuiteID, ProductID-- 订单视图
create view OrdersView
as
select
OrderID, ProductID, sum(Quantity) as Quantity
from
Orders
group by OrderID, ProductID2、评价函数为表述清晰,我们建立利用SQL2K的UDF功能建立一个评价函数,用来对某一种产品的组合数量和订单数量作出判断。create function dbo.evalDiff
(@orderQuantity int, @suiteQuantity int)
returns int as
begin
if @orderQuantity >= @suiteQuantity
return @orderQuantity - @suiteQuantity return -1000 --使用一个足够小的数量即可
end3、联结比对首先将Suite套装表与Orders订单表中的给定订单(@orderID)联结,观察其中各产品与所有套装组合的明细:select
@orderID OID, s.SuiteID, o.Quantity, s.Quantity,
(dbo.evalDiff(o.quantity, s.quantity)) Diff
from
OrdersView o, SuiteView s
where
o.Orderid = @orderID and o.ProductID =* s.ProductID
order by
SuiteID注意“=*”的非正规偷懒用法(等同于FULL JOIN),它用来选出那些S中存在但O中不存在的行(既然不存在,O.*都将为NULL)。我们可以发现,如果以OrderID和SuiteID分组汇总Diff的话,就能够知道整个套装是否匹配该定单明细,因此将上面的语句演变为:select
@orderID OID, s.SuiteID, o.Quantity, s.Quantity,
sum((dbo.evalDiff(o.quantity, s.quantity))) TotalDiff
from
OrdersView o, SuiteView s
where
o.OrderID = @orderID and o.ProductID =* s.ProductID
group by
s.SuiteID观察结果看看TotalDiff的值是否吻合预定的逻辑(存在套装则TotalDiff>=0),没有问题的话,进一步通过having子句即可达到目标,最终的语句为:select
@orderID OID, s.SuiteID, o.Quantity, s.Quantity,
sum((dbo.evalDiff(o.quantity, s.quantity))) TotalDiff
from
OrdersView o, SuiteView s
where
o.OrderID = @orderID and o.ProductID =* s.ProductID
group by
s.SuiteID
having
sum(dbo.evalDiff(o.quantity, s.quantity)) >= 0其中s.SuiteID的值就是@orderID对应订单中包含的套装的ID。附相关数据表与运行结果:Suite表:SuiteID ProductID Quantity
---------- ---------- -----------
0001 aaaa 1
0001 aaaa 1
0001 bbbb 1
0002 aaaa 1
0002 cccc 1
0002 dddd 1
0002 eeee 2Orders表(你可以自己添加新的order来测试):OrderID ProductID Quantity
---------- ---------- -----------
t0001 aaaa 1
t0002 aaaa 1
t0002 aaaa 2
t0002 bbbb 1
t0003 aaaa 1
t0003 cccc 1
t0003 dddd 1
t0003 eeee 1
t0003 eeee 1
t0004 aaaa 1
t0004 bbbb 1
t0004 cccc 1
t0004 dddd 1
t0004 eeee 1
t0004 aaaa 1
t0004 eeee 1
t0005 aaaa 1
t0005 bbbb 1
t0005 aaaa 1测试:declare @orderID char(10)
set @orderID = 't0005'(这里执行刚才的代码)结果:orderID SuiteID TotalDiff
---------- ---------- -----------
t0005 0001 0说明t0005订单中含有0001套装。后话:前面大概分析了一下解题的思路并给出了一个参考的实现方法,接下来你可以在此基础上实现更复杂的逻辑(如加入order by套装价格、成本、利润等等),将一份订单明细通过循环识别组合(记得包含在一个事务中)来生成最终的发货方案(例如:对一份订单,每次选出一个价格最高的套装组合,将其加入发货表,并从订单明细中减去,重复直到没有组合,将剩余的独立产品加入发货表)。值得注意的是,这里我们实现的仅是数据逻辑(且充分利用3GL SQL语言的处理特性),在数据库中最好不要实现业务逻辑,毕竟你还有客户端或中间层可以写4GL的高级代码(当然还有更多的原因)。尤其在多层开发中,一定要遵循一个基本设计与实现原则,即在最适合的地方做最合适的事。这种经验是在设计并开发无数个产品以后才能够体会到的,总靠一些技巧和机灵把汽车开上天是永远也不可能成为一名能够驾驭兰天的机师的。况且无数的失败或教训告诉我们,往往“败事有余”的根源恰恰在于人们对最基本的原则和规律的漠视,而这些人同样也骄傲到以为能够技巧高超的把汽车开上天就可以对飞行员嗤之以鼻了。呵呵————告诉你飞行员开车也不一定比你差噢,况且你顶多也就是开开车:)以上一些不成熟的思路仅供大家参考,我相信会有更快更好更别致的办法来完成这个“超难问题”。
套装代码 in (select 套装代码 from 表A A1 where A1.商品= and A1.数量=)
套装代码 in (select 套装代码 from 表A A1 where A1.商品= and A1.数量=)
套装代码 in (select 套装代码 from 表A A1 where A1.商品= and A1.数量=)
套装代码 in (select 套装代码 from 表A A1 where A1.商品= and A1.数量=)
套装代码 in (select 套装代码 from 表A A2 where A2.商品= and A2.数量=)
套装代码 in (select 套装代码 from 表A A3 where A3.商品= and A3.数量=)
让我受益非浅。
此帖到晚上8点结帖,如果还有朋友要关注的话,请继续。。
其实在我的系统中,我只需要输入套餐代码,然后取得套餐对应各明细商品就可以了,这是很简单的。
然后在开发的过程中,想到能不能根据输入的商品来匹配套餐(虽然客户没有提出这方面的需求,本人觉得还是有必要研究一下)。
我看了你的思路,觉得写得挺好的,基本上已经给出了整个的解决方案,应该说完全能够满足我的需求了,只是由于时间关系,所以没有去完全测试一下。
再次感谢你!!