Sql 与使用非唯一联接条件的查询大小有关
我在工作中遇到了麻烦。我在住房部门工作。我们向房屋发出订单(这样我们的承包商就可以出去修理房屋) 订单包含一个或多个作业。一个住宅没有、一个或多个针对它的命令 这是一个简短的数据定义。我已经简化了表格,但希望你能理解。一个订单可以包含多个作业,一个属性可以有多个订单Sql 与使用非唯一联接条件的查询大小有关,sql,oracle,Sql,Oracle,我在工作中遇到了麻烦。我在住房部门工作。我们向房屋发出订单(这样我们的承包商就可以出去修理房屋) 订单包含一个或多个作业。一个住宅没有、一个或多个针对它的命令 这是一个简短的数据定义。我已经简化了表格,但希望你能理解。一个订单可以包含多个作业,一个属性可以有多个订单 CREATE TABLE dwellings ( id VARCHAR2(10) PRIMARY KEY NOT NULL, address VARCHAR2(100) NOT NULL ); CREATE TABLE order
CREATE TABLE dwellings (
id VARCHAR2(10) PRIMARY KEY NOT NULL,
address VARCHAR2(100) NOT NULL
);
CREATE TABLE orders (
id VARCHAR2(10) PRIMARY KEY NOT NULL,
created_by VARCHAR2(10) NOT NULL,
created_on DATE NOT NULL,
dwelling_id VARCHAR2(10) NOT NULL REFERENCES dwellings(id)
);
CREATE TABLE jobs (
id VARCHAR2(10) PRIMARY KEY NOT NULL,
sor_id VARCHAR2(10) NOT NULL,
order_id VARCHAR2(10) NOT NULL REFERENCES orders(id)
);
并填充:
INSERT INTO dwellings VALUES ('00ABC', '2 The Mews House Little Boston London E1 1EE');
INSERT INTO dwellings VALUES ('5H88H', '3 Electric House Snodsbury S1 1IT');
INSERT INTO orders VALUES ('000001-A', 'CSMITH', DATE '2016-03-10', '00ABC');
INSERT INTO orders VALUES ('000002-A', 'CSMITH', DATE '2016-03-11', '00ABC');
INSERT INTO orders VALUES ('000003-A', 'AJONES', DATE '2016-03-16', '00ABC');
INSERT INTO orders VALUES ('000004-A', 'CSMITH', DATE '2016-03-16', '5H88H');
INSERT INTO jobs VALUES ('001', '000AA0', '000001-A');
INSERT INTO jobs VALUES ('002', '123BB0', '000001-A');
INSERT INTO jobs VALUES ('003', '000AA0', '000002-A');
INSERT INTO jobs VALUES ('004', '787XD7', '000003-A');
INSERT INTO jobs VALUES ('005', '000AA0', '000003-A');
INSERT INTO jobs VALUES ('006', '787XD7', '000004-A');
一位分析师想知道哪些代理商的订单与之前的订单相似。审查的对象是SOR_ID,它表示工作类型。请记住,每个订单都有一个或多个作业关联。因此,任务是:生成一个报告,显示包含一个或多个重复作业类型的订单,这些订单与属性中以前的订单相同
我正在构建的报告将有以下列标题
- 代理名称
- 订单号
- 地址
- 上一订单Id
- 重复作业类型
select * from orders ord
join orders ord2 on ord.dwelling_id = ord2.dwelling_id --shaky
and ord.id <> ord2.id
and ord.created_on - ord2.created_on between 0 and 90
join jobs job on job.order_id = ord.id
join jobs job2 on job2.order_id = ord2.id
where job.sor_id = job2.sor_id
从订单ord中选择*
在ord.HOLLING\u id=ord2.HOLLING\u id上连接订单ord2——不稳定
和ord.id ord2.id
和ord.created_on-ord2.created_on介于0和90之间
join jobs job on job.order\u id=ord.id
在job2.order\u id=ord2.id上加入作业job2
其中job.sor_id=job2.sor_id
我正在寻找关于如何将此查询重构为更易于管理(没有PLSQL)的建议。请注意,我没有使用滞后/超前,也没有使用Listag折叠作业类型代码。那将在以后进行。我担心目前的查询成本有多高。query:
SELECT o.created_by AS agent_name,
d.address,
LISTAGG( o.id, ',' ) WITHIN GROUP ( ORDER BY o.created_on ) AS order_ids,
j.sor_id AS job_type
FROM dwellings d
INNER JOIN orders o
ON ( o.dwelling_id = d.id )
INNER JOIN jobs j
ON ( j.order_id = o.id )
GROUP BY o.created_by, d.address, j.sor_id
HAVING COUNT(1) > 1;
AGENT_NAME ADDRESS ORDER_IDS JOB_TYPE
---------- -------------------------------------------- ----------------- ----------
CSMITH 2 The Mews House Little Boston London E1 1EE 000001-A,000002-A 000AA0
输出:
SELECT o.created_by AS agent_name,
d.address,
LISTAGG( o.id, ',' ) WITHIN GROUP ( ORDER BY o.created_on ) AS order_ids,
j.sor_id AS job_type
FROM dwellings d
INNER JOIN orders o
ON ( o.dwelling_id = d.id )
INNER JOIN jobs j
ON ( j.order_id = o.id )
GROUP BY o.created_by, d.address, j.sor_id
HAVING COUNT(1) > 1;
AGENT_NAME ADDRESS ORDER_IDS JOB_TYPE
---------- -------------------------------------------- ----------------- ----------
CSMITH 2 The Mews House Little Boston London E1 1EE 000001-A,000002-A 000AA0
列出具有不同订单ID的作业,这些作业属于同一类型,由同一代理放置在同一地址。订单在逗号分隔列表中按时间顺序列出
但是,如果您想将其与标题一起使用,则可以执行以下操作:
SELECT *
FROM (
SELECT o.created_by AS agent_name,
o.id,
d.address,
LAG( o.id ) OVER ( PARTITION BY o.created_by, d.address, j.sor_id
ORDER BY o.created_on
) AS previous_order_id,
j.sor_id AS job_type
FROM dwellings d
INNER JOIN orders o
ON ( o.dwelling_id = d.id )
INNER JOIN jobs j
ON ( j.order_id = o.id )
)
WHERE previous_order_id IS NOT NULL;
这将产生:
AGENT_NAME ID ADDRESS PREVIOUS_ORDER_ID JOB_TYPE
---------- ---------- -------------------------------------------- ----------------- ----------
CSMITH 000002-A 2 The Mews House Little Boston London E1 1EE 000001-A 000AA0
如果您想考虑多个代理,那么可以通过< <代码> > <代码> >通过< <代码> >子句,从<代码>组中删除<代码> O.CREATEDY。对于顶部查询,您需要使用
listag
获取所有代理。像这样:
SELECT LISTAGG( o.created_by, ',' ) WITHIN GROUP ( ORDER BY o.created_on ) AS agent_name,
d.address,
LISTAGG( o.id, ',' ) WITHIN GROUP ( ORDER BY o.created_on ) AS order_ids,
j.sor_id AS job_type
FROM dwellings d
INNER JOIN orders o
ON ( o.dwelling_id = d.id )
INNER JOIN jobs j
ON ( j.order_id = o.id )
GROUP BY d.address, j.sor_id
HAVING COUNT(1) > 1;
或者,对于第二个查询,如下所示:
SELECT *
FROM (
SELECT o.created_by AS agent_name,
o.id,
d.address,
LAG( o.id ) OVER ( PARTITION BY d.address, j.sor_id
ORDER BY o.created_on
) AS previous_order_id,
j.sor_id AS job_type
FROM dwellings d
INNER JOIN orders o
ON ( o.dwelling_id = d.id )
INNER JOIN jobs j
ON ( j.order_id = o.id )
)
WHERE previous_order_id IS NOT NULL;
然后,这两个查询还将输出id为
000003-A的订单,该订单由AJONES
我将尝试的更改:
ord.id ord2.id
:ord2.id
(不确定这是否适用于您)
ord.created_on-ord2.created_on介于0和90之间
:ord2.created_on=ord.created_on-90
(不确定RDBMS是否可以进行优化)
- 将
job.sor_id=job2.sor_id
移动到ON子句中(但RDBMS可能会为您这样做)
从订单ord中选择*
加入订单ord2
在ord2.HOLLING_id=ord.HOLLING_id上
和ord2.id
您将需要的索引:
- 订单(居住标识、创建标识、标识)
- 作业(订单id、订单id)
对不起,我应该提到。Oracle 11g或现在可能是12件。考虑添加[Oracle ]标签。相同的代理可能不会插入重复。但不同的代理人可能会。