Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 与使用非唯一联接条件的查询大小有关_Sql_Oracle - Fatal编程技术网

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
  • 重复作业类型
下面是到达那里的查询的开始。我没有对数据库执行它,因为有50000个属性、100000个订单和200000个作业。我关心表的大小,因为我连接的列不是唯一的

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 ]标签。相同的代理可能不会插入重复。但不同的代理人可能会。