假设有一个业务规则用于派生值,并且由于业务用户需要更新该规则,因此逻辑必须保存在表中,而不是函数中。
当前功能示例
WHEN inputA IN (1,2,3) AND inputB NOT IN (55,66) THEN OUTPUT = 'HQ'
WHEN inputA IN (3,6) AND inputB IN (27,44) THEN OUTPUT = 'Northern'
WHEN inputC IN (6,4,1) AND inputB NOT IN (55,66) THEN OUTPUT = 'Eastern'
etc.
我可以为每个组合创建一个表,其中包含一行例如
OUTPUT | A val | B val | C val val>||
---|---|---|---|---|
北部 | 3 | 27 | ||
北方 | 3 | 44 | ||
北部 | 6 | 27|||
北部 | 6 | 44 |
您可以用一个表来表示这些表达式,其中每行包含:
- 输出
- 等于?(真或假(
- 输入
- 价值
这将表示";如果(INPUT=VALUE(=EQUALS?则输出";,除了对于给定的OUTPUT/INPUT,您只需要1个令人满意的行,其中EQUALS?是真的,但所有行都必须满足EQUALS?是错误的。
这假设您只有一个";规则";对于每个不同的输出。
这里尝试使用一个包含正规则和负规则的规则表。
规则表将有效值存储为整数,但无效值存储在带分隔符的字符串中。(不确定json还是xml会更好(
但制定消极的规则会让事情变得非常棘手
因为通过为相同的输出名称添加另一个规则很容易忽略一个规则。
就我个人而言,我认为对这种类型的规则使用UDF更安全。
create table test ( id int identity(1,1) primary key, inputA int, inputB int, inputC int ) create table output_areas ( code varchar(2) primary key, name varchar(30) not null ) insert into output_areas values ('HQ', 'HQ') , ('N', 'Northern'), ('E', 'Eastern') , ('W', 'Westhern'), ('S', 'Southern') , ('X', 'Extern'), ('Z', 'The Zone') create table input_rules ( id int identity(1,1) primary key, output_area_code varchar(2) not null, relevance int not null default 0, inputA_valid int, inputB_valid int, inputC_valid int, inputA_invalid varchar(100), inputB_invalid varchar(100), inputC_invalid varchar(100), foreign key (output_area_code) references output_areas(code) ) insert into input_rules (output_area_code, relevance) values ('X', 0); insert into input_rules (output_area_code, relevance, inputA_valid) values ('Z',10, 1); insert into input_rules (output_area_code, relevance, inputA_valid, inputB_invalid) values ('HQ', 20, 1, '|55|56|') , ('HQ', 20, 2, '|55|56|') , ('HQ', 20, 3, '|55|56|') ; insert into input_rules (output_area_code, relevance, inputA_valid, inputB_valid) values ('N', 30, 3, 27), ('N', 30, 3, 44) , ('N', 30, 6, 27), ('N', 30, 6, 44) ; insert into input_rules (output_area_code, relevance, inputC_valid, inputB_invalid) values ('E', 20, 6, '|55|66|' ) , ('E', 20, 4, '|55|66|' ) ; insert into test (inputA, inputB, inputC) values (1, 56, null) , (3, 44, null), (3, 66, null) , (1, 66, null), (1, 88, null) , (null, 66, 6), (null, 88, 6)
select * from input_rules
id|output_area_code|correlation|inputA_valid|inputB_valid|inputC_valid|inputA_invalid|inputB_invalid|inputC_invalid-:|:----------------|----------------:|-----------------------------1|X|0|null|null|null|null|null|2|Z|10|1|>null|null|null 56||null4|HQ|20|2|null|null|null|55|56||2null5|HQ |20|3|1null2|3nullnullnull|null30|3|44|null|null|null8|N|30|6|27|>null>|null|null9 |N|30|6|44|nullnull|null|6|null>|55|66|>null11|E|20|1null2|2nullnull55|66|null
select * from test t outer apply ( select top 1 ref.name as output from input_rules r join output_areas ref on ref.code = r.output_area_code where (r.inputA_valid is null or r.inputA_valid = t.inputA) and (r.inputB_valid is null or r.inputB_valid = t.inputB) and (r.inputC_valid is null or r.inputC_valid = t.inputC) and (r.inputA_invalid is null or r.inputA_invalid not like concat('%|', t.inputA, '|%')) and (r.inputB_invalid is null or r.inputB_invalid not like concat('%|', t.inputB, '|%')) and (r.inputC_invalid is null or r.inputC_invalid not like concat('%|', t.inputC, '|%')) order by r.relevance desc, r.output_area_code asc ) ca
id|inputA|inputB|inputC|output-:|-----:|------------1|1|56|null|区域2|3|44|null|北方3|3|66|空|HQ4|1|66|空|HQ5|1|88 |空|HQ6|null|66|6|外部7|null|88|6|Eastern
db<gt;小提琴这里