【问题标题】:Need help designing table of rules to be used for SQL selections需要帮助设计用于 SQL 选择的规则表
【发布时间】:2011-09-26 18:46:25
【问题描述】:

我正在改进我拥有的脚本,以便最终用户可以自动化和维护它。

之前,我在this SO 帖子中提到了这个脚本的一部分。

正如Randyhis 回答中所描述的那样,SQL 语句的逻辑应该替换为表和连接的组合以完成相同的最终结果。


基本情况和目标如下:

目前,脚本将根据涉及多个变量的一组复杂规则自动为学生分配顾问。

由于员工(聘用/解雇顾问)、专业(添加/删除计划)和学时限制(确定顾问所需的最短时间)的变化,终端场景的规则将随着时间而改变。

这些规则需要在脚本/SQL 之外维护,以便最终用户(院长/部门负责人)可以管理终端场景。

需要创建一个自定义表来有效地管理这些规则。


这是当前用于执行这些规则的 SQL:

SELECT DISTINCT     s.id stu_id,
                    stu_id.fullname stu_name,
                    p.major1 major,
                    p.minor1 minor,
                    s.reg_hrs,
                    NVL(st.cum_earn_hrs,0) ttl_hrs,
                    p.adv_id curr_adv_id,
                    adv_id.fullname curr_adv_name,
                    CASE    WHEN    (p.adv_id <> 35808 AND p.major1 = 'NS')                 THEN    (1165)
                            WHEN    (p.adv_id = 35808 AND p.major1 = 'NS')                  THEN    (35808)
                            WHEN    (p.adv_id = 9179 AND p.major1 = 'DART')                 THEN    (9179)
                            WHEN    (p.minor1 IN ('RT','RESP') AND st.cum_earn_hrs >= 24)   THEN    (70897)
                            WHEN    (p.major1 IN ('CDSC','CDSD'))                           THEN    (52125)
                            WHEN    (p.major1 IN ('CA','CB'))                               THEN    (24702)
                            WHEN    (p.minor1 = 'NURS')                                     THEN    (51569)
                            WHEN    (p.major1 = 'LEG')                                      THEN    (13324)
                            WHEN    (p.major1 = 'CC')                                       THEN    (73837)
                            WHEN    (p.major1 = 'CCRE')                                     THEN    (1133)
                            WHEN    ((p.adv_id IN (SELECT DISTINCT id FROM fac_rec WHERE stat = 'I'))
                                    OR (st.cum_earn_hrs < 24 AND (p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0 AND min_hrs >= 24))
                                    OR (s.id NOT IN (SELECT DISTINCT stu.id FROM stu_acad_rec stu, sess_info si WHERE stu.yr = si.prev_yr AND stu.sess = si.prev_sess AND stu.reg_hrs > 0 AND stu.reg_stat IN ('C','R') AND stu.prog = 'UNDG'))
                                    OR ((p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat <> 'A' OR max_stu <= 0))
                                    OR ((p.adv_id||p.major1) NOT IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0)))
                            THEN    (9238)
                            ELSE    (p.adv_id)
                    END     new_adv_id,
                    CASE    WHEN    (p.adv_id <> 35808 AND p.major1 = 'NS')                 THEN    ('Deborah')
                            WHEN    (p.adv_id = 35808 AND p.major1 = 'NS')                  THEN    ('Veronica')
                            WHEN    (p.adv_id = 9179 AND p.major1 = 'DART')                 THEN    ('Stella')
                            WHEN    (p.minor1 IN ('RT','RESP') AND st.cum_earn_hrs >= 24)   THEN    ('Lisa')
                            WHEN    (p.major1 IN ('CDSC','CDSD'))                           THEN    ('Joanne')
                            WHEN    (p.major1 IN ('CA','CB'))                               THEN    ('Barbara')
                            WHEN    (p.minor1 = 'NURS')                                     THEN    ('Karen')
                            WHEN    (p.major1 = 'LEG')                                      THEN    ('Nancy')
                            WHEN    (p.major1 = 'CC')                                       THEN    ('Alberta')
                            WHEN    (p.major1 = 'CCRE')                                     THEN    ('Naomi')
                            WHEN    ((p.adv_id IN (SELECT DISTINCT id FROM fac_rec WHERE stat = 'I'))
                                    OR (st.cum_earn_hrs < 24 AND (p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0 AND min_hrs >= 24))
                                    OR (s.id NOT IN (SELECT DISTINCT stu.id FROM stu_acad_rec stu, sess_info si WHERE stu.yr = si.prev_yr AND stu.sess = si.prev_sess AND stu.reg_hrs > 0 AND stu.reg_stat IN ('C','R') AND stu.prog = 'UNDG'))
                                    OR ((p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat <> 'A' OR max_stu <= 0))
                                    OR ((p.adv_id||p.major1) NOT IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0)))
                            THEN    ('Staff')
                            ELSE    (adv_id.fullname)
                    END     new_adv_name,
                    CASE    WHEN    (p.adv_id <> 35808 AND p.major1 = 'NS')                 THEN    ('NS majors not assigned to Veronica go to Debbie')
                            WHEN    (p.adv_id = 35808 AND p.major1 = 'NS')                  THEN    ('NS majors stay with Veronica')
                            WHEN    (p.adv_id = 9179 AND p.major1 = 'DART')                 THEN    ('DART majors stay with Stella')
                            WHEN    (p.minor1 IN ('RT','RESP') AND st.cum_earn_hrs >= 24)   THEN    ('RT-RESP minors go to Lisa')
                            WHEN    (p.major1 IN ('CDSC','CDSD'))                           THEN    ('CDSC-CDSD majors go to Joanne')
                            WHEN    (p.major1 IN ('CA','CB'))                               THEN    ('CA-CB majors go to Barbara')
                            WHEN    (p.minor1 = 'NURS')                                     THEN    ('NURS minors go to Karen')
                            WHEN    (p.major1 = 'LEG')                                      THEN    ('LEG majors go to Nancy')
                            WHEN    (p.major1 = 'CC')                                       THEN    ('CC majors go to Alberta')
                            WHEN    (p.major1 = 'CCRE')                                     THEN    ('CCRE majors go to Naomi')
                            WHEN    (p.adv_id IN (SELECT DISTINCT id FROM fac_rec WHERE stat = 'I'))
                            THEN    ('Current advisor is inactive')
                            WHEN    (st.cum_earn_hrs < 24 AND (p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0 AND min_hrs >= 24))
                            THEN    ('Total credits for this student did not meet the advisor reqs for this major')
                            WHEN    (s.id NOT IN (SELECT DISTINCT stu.id FROM stu_acad_rec stu, sess_info si WHERE stu.yr = si.prev_yr AND stu.sess = si.prev_sess AND stu.reg_hrs > 0 AND stu.reg_stat IN ('C','R') AND stu.prog = 'UNDG'))
                            THEN    ('This student did not attend '||si.prev_sess||si.prev_yr)
                            WHEN    ((p.adv_id||p.major1) IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE (stat <> 'A' OR max_stu <= 0)))
                            THEN    ('Current advisor is not advising students with this major')
                            WHEN    ((p.adv_id||p.major1) NOT IN (SELECT DISTINCT (id||major) FROM adv_detail WHERE stat = 'A' AND max_stu > 0))
                            THEN    ('Current advisor is not advising students with this major')
                            ELSE    ('Student will stay with current advisor')
                    END     change_comm
FROM                stu_acad_rec s,
                    prog_enr_rec p,
                    OUTER stu_stat_rec st,
                    id_rec stu_id,
                    id_rec adv_id,
                    sess_info si
WHERE               s.id = p.id
                    AND s.id = st.id
                    AND s.id = stu_id.id
                    AND p.adv_id = adv_id.id
                    AND s.yr = si.curr_yr
                    AND s.sess = si.curr_sess
                    AND s.reg_hrs > 0
                    AND s.reg_stat IN ('C','R')
                    AND s.prog = 'UNDG'
                    AND p.prog = 'UNDG'
                    AND st.prog = 'UNDG'
                    AND s.id NOT IN (3,287,9238,59999) {System test use IDs}
INTO TEMP           stu_list
WITH NO LOG;

我正在尝试构建一个表格来保存所有这些规则,但从未创建过具有这种用途的表格。

到目前为止,我的想法是一个具有这种结构的表:

adv_assign_rules
----------------
rule_no
curr_adv_id
major1
major2
minor1
minor2
cum_earn_hrs
new_adv_id
rule_desc
rule_no_ref
rule_stat
rule_date

此表的示例行将容纳 SQL 选择中的第一种情况,可能如下所示:

rule_no         1
curr_adv_id     !35808
major1          =NS
major2
minor1
minor2
cum_earn_hrs
new_adv_id      1165
rule_desc       NS majors not assigned to 35808 go to Debbie
rule_no_ref
rule_stat       A
rule_date       2011-09-26 15:02:26.000

这样的桌子有什么缺陷吗?这种类型的设置可以适应所有这些规则吗?有谁知道在哪里可以找到用于类似目的的表格示例?

我正在寻找有关此问题的改进和/或替代解决方案的建议。这些案例陈述中的“其他”场景表明不需要更改学生的顾问。此外,其中包含最多逻辑的案例(“else”案例之前的最后一个案例)将新顾问默认为 9238 - 这表明已经存在的其他逻辑将用于分配新的 adivsor。之前的所有案例都是默认场景,它们是不遵循分配新顾问规则的特殊案例——这些是我试图以表格格式重新创建的特殊案例。

更新:我也在寻找重现和/或场景的功能。我添加了两个字段:rule_no & rule_no_ref,分别是一个序列号(自动递增)和对另一个规则序列号的引用。

在此先感谢您提供的任何帮助!

【问题讨论】:

  • 我想你可能想为此保留CASE。如果没有某种循环,将很难复制短路行为。一种可能性是使用动态 SQL 并使用每个场景的 CASE 条件填充您的表。
  • 如果我是唯一打算维护它的人,我会保留它,但最终用户需要一种方法来调整这些规则。我会考虑你的其他建议 - 谢谢

标签: sql database-design case rules


【解决方案1】:

我会绕过这个略有不同:

1) 创建表 rule_type

id 
name 

2) 创建表rule_set

id   -- rule 
type -- relation to talbe 1
name 
staff_group -- relation to the appropriate staff group for that rule
student_group  -- relation to the appropriate student group for that rule
val_int --- for the rules that require numeric number
val_chr --- for rules that require integer values
val_date --- for date values rules
date_start --- start date of a rule
date_end  --- end date of a rule

您还可以为区间参数创建字段,例如从 X ... Y 的整数范围,例如: val_int_start val_int_end 或任何其他数据类型

然后创建一个存储过程来处理规则并评估适当的数据

这种方法的好处是,从长远来看,您真的很少需要编写新代码

【讨论】:

  • 感谢您的回答...问题是这没有考虑比较属性(例如: >=
猜你喜欢
  • 2010-11-11
  • 2020-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多