我有一个任务交付时间表,它基于任务部门(仅)、任务类别(仅)或产品任务和类别。这些规则可以直接应用于一个客户、一组客户或所有客户。
例子:
- 客户 01 + 部门:设计 + 类别:创建徽标 = 24 小时
- 客户 01 + 部门:设计 + 任何类别 = 48 小时全部
- 客户 + 部门:设计 + 任何类别 = 72 小时全部
- 客户 + 任何类别 + 类别:创建徽标 = 48 小时
该表的结构如下:
|rule_id|customer_id|departament_id|category_id|deadline|
创建表的 SQL:
CREATE TABLE public.test_customer (
id INTEGER NOT NULL,
name varchar(50) NOT NULL
);
CREATE TABLE public.test_departament (
id INTEGER NOT NULL,
name varchar(50) NOT NULL
);
CREATE TABLE public.test_category (
id INTEGER NOT NULL,
name varchar(50) NOT NULL
);
CREATE TABLE public.test_task (
id INTEGER NOT NULL,
customer_id INTEGER,
departament_id INTEGER,
category_id INTEGER,
description varchar(50) NOT NULL
);
CREATE TABLE public.test_time_rule (
id INTEGER NOT NULL,
customer_id INTEGER,
departament_id INTEGER,
category_id INTEGER,
time_deadline INTEGER
);
INSERT INTO public.test_customer (id, name) VALUES(1, 'Customer with Rule');
INSERT INTO public.test_customer (id, name) VALUES(2, 'Customer without Rule');
INSERT INTO public.test_departament (id, name) VALUES(1, 'Front-End');
INSERT INTO public.test_departament (id, name) VALUES(2, 'Back-End');
INSERT INTO public.test_departament (id, name) VALUES(3, 'DBA');
INSERT INTO public.test_departament (id, name) VALUES(1, 'Design');
INSERT INTO public.test_departament (id, name) VALUES(2, 'Create HTML Pages');
INSERT INTO public.test_departament (id, name) VALUES(3, 'Create Tables');
INSERT INTO public.test_departament (id, name) VALUES(4, 'Fix Bugs');
INSERT INTO public.test_task (id, customer_id, departament_id, category_id, description) VALUES(1, 1, 1, 1, 'Create New Form Design');
INSERT INTO public.test_task (id, customer_id, departament_id, category_id, description) VALUES(2, 1, 2, 4, 'Fix Bug on Customer Table');
INSERT INTO public.test_task (id, customer_id, departament_id, category_id, description) VALUES(2, 1, 3, 3, 'Create City Table');
INSERT INTO public.test_task (id, customer_id, departament_id, category_id, description) VALUES(3, 2, 1, 1, 'Create New Form Design');
INSERT INTO public.test_task (id, customer_id, departament_id, category_id, description) VALUES(4, 2, 3, 3, 'Create City Table');
INSERT INTO public.test_time_rule (id, customer_id, departament_id, category_id, time_deadline) VALUES(1, NULL, NULL, NULL, 20); --All Customers
INSERT INTO public.test_time_rule (id, customer_id, departament_id, category_id, time_deadline) VALUES(2, NULL, 1, NULL, 30); --All Customers + Departament
INSERT INTO public.test_time_rule (id, customer_id, departament_id, category_id, time_deadline) VALUES(3, NULL, NULL, 1, 40); --All Customers + Category
INSERT INTO public.test_time_rule (id, customer_id, departament_id, category_id, time_deadline) VALUES(4, NULL, 3, 3, 50); --All Customers + Departament + Category
INSERT INTO public.test_time_rule (id, customer_id, departament_id, category_id, time_deadline) VALUES(5, 1, NULL, NULL, 20); --Customers With Rule
INSERT INTO public.test_time_rule (id, customer_id, departament_id, category_id, time_deadline) VALUES(6, 1, 1, NULL, 30); --Customers + Departament
INSERT INTO public.test_time_rule (id, customer_id, departament_id, category_id, time_deadline) VALUES(7, 1, NULL, 1, 40); --Customers + Category
INSERT INTO public.test_time_rule (id, customer_id, departament_id, category_id, time_deadline) VALUES(8, 1, 3, 3, 50); --Customers + Departament + Category
我正在尝试创建一个SELECT
列出所有任务并显示适用于它的规则。为此,我正在使用规则的应用程序级别,它们是:
1 - 客户 + 部门 + 类别的规则(定义的客户 ID)
2 - 客户组 + 部门 + 类别的规则(定义的客户组 ID)
3 - 一般规则(所有客户)+ 部门 + 类别(未定义客户和客户组 ID)
4 - 客户+部门规则
我已经总结了这些规则,但它们最多可达到 16 条规则,并且我为每个规则创建了一个视图,其中包含与其参数匹配的任务。
基于这些规则,我创建了SELECT
几个UNION ALL
(性能原因),但由于之前的选择可以重复该行,我最终添加了NOT EXISTS
条件来防止这个问题。
例子:
SELECT
1 as level,
ttr.id as rule_id,
ttr.customer_id as rule_customer_id,
tt.customer_id as task_customer_id,
ttr.departament_id as rule_departament_id,
tt.departament_id as task_departament_id,
ttr.category_id as rule_category_id,
tt.category_id as task_category_id,
tt.id as task_id,
tt.description as task_description,
ttr.time_deadline
FROM
test_time_rule ttr,
test_task tt
WHERE
ttr.customer_id IS NOT NULL
AND ttr.departament_id IS NOT NULL
AND ttr.category_id IS NOT NULL
AND tt.customer_id = ttr.customer_id
AND tt.departament_id = ttr.departament_id
AND tt.category_id = ttr.category_id
UNION
SELECT
2 as level,
ttr.id as rule_id,
ttr.customer_id as rule_customer_id,
tt.customer_id as task_customer_id,
ttr.departament_id as rule_departament_id,
tt.departament_id as task_departament_id,
ttr.category_id as rule_category_id,
tt.category_id as task_category_id,
tt.id as task_id,
tt.description as task_description,
ttr.time_deadline
FROM
test_time_rule ttr,
test_task tt
WHERE
ttr.customer_id IS NULL
AND ttr.departament_id IS NOT NULL
AND ttr.category_id IS NOT NULL
AND tt.departament_id = ttr.departament_id
AND tt.category_id = ttr.category_id
UNION
SELECT
3 as level,
ttr.id as rule_id,
ttr.customer_id as rule_customer_id,
tt.customer_id as task_customer_id,
ttr.departament_id as rule_departament_id,
tt.departament_id as task_departament_id,
ttr.category_id as rule_category_id,
tt.category_id as task_category_id,
tt.id as task_id,
tt.description as task_description,
ttr.time_deadline
FROM
test_time_rule ttr,
test_task tt
WHERE
ttr.customer_id IS NOT NULL
AND ttr.departament_id IS NOT NULL
AND ttr.category_id IS NULL
AND tt.customer_id = ttr.customer_id
AND tt.departament_id = ttr.departament_id
UNION
SELECT
4 as level,
ttr.id as rule_id,
ttr.customer_id as rule_customer_id,
tt.customer_id as task_customer_id,
ttr.departament_id as rule_departament_id,
tt.departament_id as task_departament_id,
ttr.category_id as rule_category_id,
tt.category_id as task_category_id,
tt.id as task_id,
tt.description as task_description,
ttr.time_deadline
FROM
test_time_rule ttr,
test_task tt
WHERE
ttr.customer_id IS NULL
AND ttr.departament_id IS NOT NULL
AND ttr.category_id IS NULL
AND tt.departament_id = ttr.departament_id
UNION
SELECT
5 as level,
ttr.id as rule_id,
ttr.customer_id as rule_customer_id,
tt.customer_id as task_customer_id,
ttr.departament_id as rule_departament_id,
tt.departament_id as task_departament_id,
ttr.category_id as rule_category_id,
tt.category_id as task_category_id,
tt.id as task_id,
tt.description as task_description,
ttr.time_deadline
FROM
test_time_rule ttr,
test_task tt
WHERE
ttr.customer_id IS NOT NULL
AND ttr.departament_id IS NULL
AND ttr.category_id IS NOT NULL
AND tt.customer_id = ttr.customer_id
AND tt.category_id = ttr.category_id
UNION
SELECT
6 as level,
ttr.id as rule_id,
ttr.customer_id as rule_customer_id,
tt.customer_id as task_customer_id,
ttr.departament_id as rule_departament_id,
tt.departament_id as task_departament_id,
ttr.category_id as rule_category_id,
tt.category_id as task_category_id,
tt.id as task_id,
tt.description as task_description,
ttr.time_deadline
FROM
test_time_rule ttr,
test_task tt
WHERE
ttr.customer_id IS NULL
AND ttr.departament_id IS NULL
AND ttr.category_id IS NOT NULL
AND tt.category_id = ttr.category_id
UNION
SELECT
7 as level,
ttr.id as rule_id,
ttr.customer_id as rule_customer_id,
tt.customer_id as task_customer_id,
ttr.departament_id as rule_departament_id,
tt.departament_id as task_departament_id,
ttr.category_id as rule_category_id,
tt.category_id as task_category_id,
tt.id as task_id,
tt.description as task_description,
ttr.time_deadline
FROM
test_time_rule ttr,
test_task tt
WHERE
ttr.customer_id IS NOT NULL
AND ttr.departament_id IS NULL
AND ttr.category_id IS NULL
AND tt.customer_id = ttr.customer_id
UNION
SELECT
8 as level,
ttr.id as rule_id,
ttr.customer_id as rule_customer_id,
tt.customer_id as task_customer_id,
ttr.departament_id as rule_departament_id,
tt.departament_id as task_departament_id,
ttr.category_id as rule_category_id,
tt.category_id as task_category_id,
tt.id as task_id,
tt.description as task_description,
ttr.time_deadline
FROM
test_time_rule ttr,
test_task tt
WHERE
ttr.customer_id IS NULL
AND ttr.departament_id IS NULL
AND ttr.category_id IS NULL
ORDER BY
level;
正如您可能已经注意到,在它进入的每个级别上,都会添加所有以前的视图,这会生成一个大而慢的 SQL。
我的常识告诉我,这不是进行咨询的最佳方式。
我考虑了一些基于先前联合中已显示的任务 ID 忽略行的东西。有没有更好的方法来创建这个 SELECT?
注意:我无法添加任务中使用的规则 ID,因为此规则可以更改、删除,甚至在将来添加到与任务最匹配的规则中。
如果你想
task_id
变得独一无二,那么像这样的东西怎么样:task_id
这将以指定的顺序返回每个的第一行。