我有一个tranctions表,我需要在其中获取5种不同牵引力的转换日期和时间(订单下降,订单选择,标有订单的地址,已加载并已发货)。
对于每个订单,我都尝试获取特定日期以及我们在该日期发货的订单的这些转换时间。我的查询几乎每个人都会运行以获取这些信息。
是否有更好的方法重写?非常感谢您的帮助。
SELECT
"ORDER",
MAX(CASE WHEN "ACTION" = 'DNLD' THEN TO_CHAR(datetimecreated,'yyyy-mm-dd
hh24:mi') END) AS ORDER_Drop_time,
MAX(CASE WHEN "ACTION" = 'REQUEST' THEN TO_CHAR(datetimecreated,'yyyy-mm-dd hh24:mi') END) AS Label_request_time,
MAX(CASE WHEN "ACTION" = 'PICK' THEN TO_CHAR(datetimecreated,'yyyy-mm-dd hh24:mi') END) AS pick_time,
MAX(CASE WHEN "ACTION" = 'LOAD' THEN TO_CHAR(datetimecreated,'yyyy-mm-dd hh24:mi') END) AS Load_TIME,
MAX(CASE WHEN "ACTION" = 'SHIP' THEN TO_CHAR(datetimecreated,'yyyy-mm-dd hh24:mi') END) AS SHIP_COM_TIME
FROM
historymaster hm
WHERE
"ORDER" IN (
SELECT
"ORDER"
FROM
historymaster
WHERE
datetimecreated >=:usestartdate
AND datetimecreated <=:useenddate
AND "ACTION" = 'SHIP'
AND "OBJECT" = 'OBORDLINE'
) -- Looking up order ID for ship transations and using it
AND (
(-- Order drop
"ACTION" = 'DNLD'
AND "OBJECT" = 'OBORDLINE'
AND actionmodifier IS NULL
AND reasoncode = '00'
)
OR --Address label request
(
"ACTION" = 'REQUEST'
AND "OBJECT" = 'LABEL'
AND "CLASS" = 'ADDR'
)
OR -- pick
(
"ACTION" = 'PICK'
AND "OBJECT" = 'OBO'
AND "CLASS" = 'INVE'
AND actualquantity != 0
AND substr(ordertype,1,1) = 'N'
)
OR -- Trailer Load
(
"ACTION" = 'LOAD'
AND "OBJECT" = 'OBO'
AND "CLASS" = 'INVE'
)
OR --Ship Complete
(
"OBJECT" = 'OBORDLINE'
AND hm.package = ' '
AND actionmodifier IS NULL
AND "ACTION" = 'SHIP'
)
)
GROUP BY
"ORDER";
输出:
ORDER ORDER_Drop_time Label_request_time PICK_TIME Load_TIME SHIP_COM_TIME
D2KJJKJLB-35689 8/2/2018 9:50 8/6/2018 9:50 8/6/2018 8:50 8/6/2018 10:50 8/7/2018 14:16
答案 0 :(得分:0)
如果查询变慢,则应使用索引。
我能想到的最重要的索引是:
create index ix1 on historymaster ("OBJECT", "ACTION", datetimecreated);
此外,如果您确实希望此查询更快,则可以添加:
create index ix2 on historymaster ("OBJECT", "ACTION", reasoncode);
create index ix3 on historymaster ("OBJECT", "ACTION", "CLASS");
请注意不要向我们的表添加太多索引,因为它会使您的INSERT
,UPDATE
和DELETE
变慢。您需要找到一个平衡点。
请检索查询的执行计划。为此:
准备检索:
drop table plan_table;
创建执行计划:
explain plan for
select ...
获取执行计划:
select plan_table_output
from table(dbms_xplan.display('plan_table',null,'typical'));
获得后,将计划添加到您的问题中。
答案 1 :(得分:0)
您的查询基本上执行两次访问,因此(假设您仅选择少量订单)您需要两个索引来反映它。
第一个索引在给定的时间范围内选择orders
和action
适当的object
("ACTION","OBJECT",datetimecreated)
第二个索引然后查询所有具有请求的orders
和action
的{{1}}的记录
object
为演示主体,我创建了一个测试表,其中包含200万行和10万个订单(请参见下面的脚本)。
请注意,我不使用保留名称(例如,“ ORDER”为order_id),而对操作和对象使用“中性”名称。
("ORDER", "ACTION" ,"OBJECT")
您期望此执行计划-内部NESTED LOOP执行上述两个访问-请参阅 访问条件5和7。
select order_id,
max(case when action_id = 'A1' then datetimecreated end) as A1_date,
max(case when action_id = 'A2' then datetimecreated end) as A2_date,
max(case when action_id = 'A3' then datetimecreated end) as A3_date,
max(case when action_id = 'A4' then datetimecreated end) as A4_date,
max(case when action_id = 'A5' then datetimecreated end) as A5_date
from test
where order_id in (
select order_id
from test
where datetimecreated >= DATE'2018-02-05' and datetimecreated <= DATE'2018-02-06' and
action_id = 'A1' and object_id = 'O1')
AND
(action_id = 'A1' and object_id = 'O1' or
action_id = 'A2' and object_id = 'O2' or
action_id = 'A3' and object_id = 'O3' or
action_id = 'A4' and object_id = 'O4' or
action_id = 'A5' and object_id = 'O1')
group by order_id;
ORDER_ID A1_DATE A2_DATE A3_DATE A4_DATE A5_DATE
---------- -------- -------- -------- -------- --------
826 05.02.18 10.02.18 15.02.18 20.02.18 21.02.18
833 05.02.18 10.02.18 15.02.18 20.02.18 21.02.18
.....
823 05.02.18 10.02.18 15.02.18 20.02.18 21.02.18
838 05.02.18 10.02.18 15.02.18 20.02.18 21.02.18
25 rows selected.
Elapsed: 00:00:00.10
这里是生成测试数据以供播放的脚本:
Plan hash value: 1930696803
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 223 | 13380 | 12 (9)| 00:00:01 |
| 1 | HASH GROUP BY | | 223 | 13380 | 12 (9)| 00:00:01 |
| 2 | NESTED LOOPS | | | | | |
| 3 | NESTED LOOPS | | 223 | 13380 | 11 (0)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 30 | 4 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | TEST_IDX1 | 1 | | 3 (0)| 00:00:01 |
| 6 | INLIST ITERATOR | | | | | |
|* 7 | INDEX RANGE SCAN | TEST_IDX2 | 1 | | 6 (0)| 00:00:01 |
| 8 | TABLE ACCESS BY INDEX ROWID | TEST | 502 | 15060 | 7 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("ACTION_ID"='A1' AND "OBJECT_ID"='O1' AND
"DATETIMECREATED">=TO_DATE(' 2018-02-05 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"DATETIMECREATED"<=TO_DATE(' 2018-02-06 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
7 - access("ORDER_ID"="ORDER_ID" AND ("ACTION_ID"='A1' AND "OBJECT_ID"='O1' OR
"ACTION_ID"='A2' AND "OBJECT_ID"='O2' OR "ACTION_ID"='A3' AND "OBJECT_ID"='O3' OR
"ACTION_ID"='A4' AND "OBJECT_ID"='O4' OR "ACTION_ID"='A5' AND "OBJECT_ID"='O1'))