希望在这里挑选人们的智慧。 (目前的方法在底部)
请参阅下面的SQL Fiddle Link。 http://sqlfiddle.com/#!17/4a818/1
create table paymentmethod (
methodtype varchar(6) not null,
methodname varchar(6) not null
);
insert into paymentmethod values
('cc', 'mstr'),
('cc', 'visa'),
('cc', 'amex')
;
create table chargepolicy (
accountname varchar(6) not null,
methodtype varchar(6) not null,
methodname varchar(6) not null,
chargerate float not null
);
insert into chargepolicy values
('acct1','cc', 'mstr', 0.02),
('acct1','cc', 'visa', 0.02),
('acct1','cc', 'amex', 0.025),
('acct2','cc', 'all', 0.015),
('acct3','cc', 'amex', 0.03),
('acct3','cc', 'all', 0.02),
('acct4','cc', 'visa', 0.0),
('acct4','cc', 'all', 0.025)
;
select * from chargepolicy, paymentmethod
where chargepolicy.methodtype = paymentmethod.methodtype
and (chargepolicy.methodname = paymentmethod.methodname
or chargepolicy.methodname = 'all')
order by 1,2,3;
所以,这是一个假设的案例(显然)。我有Visa,MasterCard,Amex等付款方式,然后是每种方法的收费标准。费率将根据帐户而有所不同。这些解释方法&速率映射在另一个表中定义。
现在,当我为每种方法定义费率时,一切正常(例如acct1和acct2)。当我们来到acct3和acct4时,事情变得有趣 - 这就是我需要帮助的地方。在acct3中,我说对于美国运通而言,收费应该是3%,而对于其他一切(所有 - 美国运通卡),它应该是2%。同样,在acct4中,我希望Visa的费用为0%,其他一切费用为2.5%。
当前SQL的编写方式,我得到了acct3.amex和acct4.visa的两个值。
我该如何简化呢。它必须是一个直截了当的东西,但我不相信我正在看它。
这就是我的想法:
http://sqlfiddle.com/#!17/36a1c/6
select *
from
chargepolicy,
paymentmethod
where
chargepolicy.methodtype = paymentmethod.methodtype
and (chargepolicy.methodname = paymentmethod.methodname
or (chargepolicy.methodname = 'all'
and paymentmethod.methodname not in (
select methodname from chargepolicy cp2 where cp2.accountname = chargepolicy.accountname
and cp2.methodname !='all')
))
order by 1,2,3;
但是由于我的实际用例有很多其他选项需要映射(例如国家,产品,货币等),我不确定我当前的方法是否可扩展 - 嵌套查询太多。
答案 0 :(得分:1)
我的方法就是这样,我认为它更容易理解。
select
ac.accountname,
pm.methodtype,
pm.methodname,
coalesce(cp1.chargerate,cp2.chargerate) as chargerate
from
paymentmethod as pm
join (select distinct accountname from chargepolicy) as ac on 1=1
left join chargepolicy as cp1 on pm.methodname=cp1.methodname and ac.accountname=cp1.accountname
left join chargepolicy as cp2 on cp2.methodname='all' and ac.accountname=cp2.accountname
order by 1,2,3;