How to fill dates in between in subquery? - clickhouse

I have got a table with purchases:
player_id | date | registration_date | price
pl1 | 2019-01-21 | 2019-01-20 | 20
pl1 | 2019-01-23 | 2019-01-20 | 10
pl1 | 2019-01-24 | 2019-01-20 | 15
After calculations with groupArray on 'date' and arrayCumSum on 'price' and using ArrayJoin I got the table with cumulative sum on each day:
player_id | date | registration_date | sum_price
pl1 | 2019-01-21 | 2019-01-20 | 20
pl1 | 2019-01-23 | 2019-01-20 | 30
pl1 | 2019-01-24 | 2019-01-20 | 45
But I need to add missing dates since registration until today (today is '2019-01-25'):
player_id | date | registration_date | sum_price
pl1 | 2019-01-20 | 2019-01-20 | 0
pl1 | 2019-01-21 | 2019-01-20 | 20
pl1 | 2019-01-22 | 2019-01-20 | 20
pl1 | 2019-01-23 | 2019-01-20 | 30
pl1 | 2019-01-24 | 2019-01-20 | 45
pl1 | 2019-01-25 | 2019-01-20 | 45
How can I do it?

Try this one:
SELECT player_id, result.1 as date, registrationDate as registration_date, result.2 as sum_price
FROM
(
SELECT
player_id,
groupArray((date, price)) AS purchases,
min(registration_date) AS registrationDate,
arrayMap(x -> registrationDate + x, range(toUInt32(toDate('2019-01-25') - registrationDate + 1))) dates,
arrayFilter(x -> arrayFirstIndex(p -> p.1 = x, purchases) = 0, dates) AS missed_dates,
arrayMap(x -> (x, 0), missed_dates) AS dummy_purchases,
arraySort(x -> x.1, arrayConcat(purchases, dummy_purchases)) all_purchases,
arrayCumSum(x -> x.2, all_purchases) cum_prices,
arrayMap(index -> (all_purchases[index].1, cum_prices[index]), arrayEnumerate(all_purchases)) flat_result,
arrayJoin(flat_result) result
FROM test.purchases01
GROUP BY player_id
)
/* result
┌─player_id─┬───────date─┬─registration_date─┬─sum_price─┐
│ pl1 │ 2019-01-20 │ 2019-01-20 │ 0 │
│ pl1 │ 2019-01-21 │ 2019-01-20 │ 20 │
│ pl1 │ 2019-01-22 │ 2019-01-20 │ 20 │
│ pl1 │ 2019-01-23 │ 2019-01-20 │ 30 │
│ pl1 │ 2019-01-24 │ 2019-01-20 │ 45 │
│ pl1 │ 2019-01-25 │ 2019-01-20 │ 45 │
└───────────┴────────────┴───────────────────┴───────────┘
*/
/* Prepare test data */
CREATE TABLE test.purchases01
(
`player_id` String,
`date` Date,
`registration_date` Date,
`price` int
)
ENGINE = Memory;
INSERT INTO test.purchases01
VALUES ('pl1', '2019-01-21', '2019-01-20', 20),
('pl1', '2019-01-23', '2019-01-20', 10),
('pl1', '2019-01-24', '2019-01-20', 15);

Related

Performance drop returning cursor with union all

I'm facing unsolvable and impossible performace drop while using UNION ALL with two sub-queries in one cursor (at least I think that's the problem). PL/SQL Developer just freezes when opening cursor results in test window.
If I turn off no matter which sub-query - everything works fine.
If I take the whole query out of cursor to regular SQL Query windows - everything is okay without any need to turn off some parts.
Procedure structure is down below, looking forward any help:
procedure p_proc(p_param varchar2,
outcur out sys_refcursor) is
begin
open outcur for
select *
from (select -- visible cols
si.item_full_name
, si.final_price
, si.full_price
, si.receipt_num
, si.receipt_date
, si.vendor_code
, case when det.br_summary is null and mr.motiv_rate_value is not null then mr.motiv_rate_value
when det.br_summary is not null then det.br_summary
end personal_bonus_amount
, case when det.br_summary is null and mr.motiv_rate_value is not null then 1
when det.br_summary is not null then det.cross_sale_kt
end personal_bonus_koeff
-- service cols
, case when det.br_summary is null and mr.motiv_rate_value is not null then 'approximate'
when det.br_summary is not null then 'definite'
end personal_bonus_type
, coalesce(det.sale_stream, mr.sale_stream, 'Not defined') item_group_name
, si.operation_type
, si.src
-- pagination
, row_number() over (order by si.receipt_date desc) rn
from (-- curr day
select b.cost final_price
, case when b.discount = 0 then null else b.price
end full_price
, b.doc_number receipt_num
, b.receipt_date receipt_date
, i.item_code vendor_code
, i.full_name item_full_name
, b.subsite code_op
, b.operator_id
, to_char(b.businessday, 'yyyymm') sale_period
, b.oper_type operation_type
, 'bill' src
from scheme.bills b
join scheme.items i on i.item_code = b.item
where b.businessday = trunc(p_date_to)
and b.subsite = p_office_id
and b.operator_id = p_emp_id
union all
-- prev days
select l.txn_amount final_price
, case when l.disc = 0 then null else l.price
end full_price
, t.receipt_num receipt_num
, t.ts receipt_date
, i.item_code vendor_code
, i.full_name item_full_name
, s.office_code code_op
, e.emp_code operator_id
, to_char(l.dt,'yyyymm') sale_period
, l.txn_type operation_type
, 'txn' src
from scheme.txn t
join scheme.txn_lines l on t.rtl_txn_id = l.rtl_txn_id
join scheme.items i on l.item_id = i.item_id
join scheme.offices s on t.subsite_id = s.subsite_id
join scheme.employees e on t.employee_id = e.employee_id
where t.ts between trunc(p_date_from) and trunc(p_date_to)
and t.subsite_id = v_op_id
and t.employee_id = v_emp_id
) si
/* fact */
left join scheme.sales_details det on si.sale_period = det.period
and si.code_op = det.op_code
and ltrim(si.operator_id,'0') = ltrim(det.tab_num,'0')
and si.receipt_num = det.rcpt_num
and si.vendor_code = det.item_article
/* prognosis */
left join scheme.rates mr on si.sale_period = mr.motiv_rate_period
and si.code_op = mr.code_op
and si.vendor_code = mr.code_1c
where 1 = 1
and si.final_price between nvl(p_price_from, si.final_price) and nvl(p_price_to, si.final_price)
/* if no filters */
and (item_group_cnt = 0 or coalesce(det.sale_stream, mr.sale_stream, 'Not defined') in (select * from table(p_item_group)))
and si.receipt_num = nvl(p_receipt_num, si.receipt_num)
)
where rn between p_page_num * p_page_size + 1 and (p_page_num + 1) * p_page_size;
end;
UPD Explain plan for the whole query used in a cursor:
----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
----------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 32810 | 62 | 00:00:01 |
| * 1 | VIEW | | 10 | 32810 | 62 | 00:00:01 |
| * 2 | WINDOW SORT PUSHED RANK | | 2 | 2956 | 62 | 00:00:01 |
| 3 | NESTED LOOPS OUTER | | 2 | 2956 | 61 | 00:00:01 |
| 4 | NESTED LOOPS OUTER | | 2 | 2826 | 53 | 00:00:01 |
| 5 | VIEW | | 2 | 2728 | 46 | 00:00:01 |
| 6 | UNION-ALL | | | | | |
| 7 | NESTED LOOPS | | 1 | 138 | 32 | 00:00:01 |
| 8 | NESTED LOOPS | | 1 | 138 | 32 | 00:00:01 |
| 9 | PARTITION RANGE SINGLE | | 1 | 66 | 29 | 00:00:01 |
| * 10 | TABLE ACCESS BY LOCAL INDEX ROWID BATCHED | F003_BILL | 1 | 66 | 29 | 00:00:01 |
| * 11 | INDEX RANGE SCAN | IX_SUBSITE_DOCNUM_BUSINDAY_SEQ | 1 | | 5 | 00:00:01 |
| * 12 | INDEX RANGE SCAN | IX_D001_CODE_1C_ITEM_ID | 1 | | 2 | 00:00:01 |
| 13 | TABLE ACCESS BY INDEX ROWID | D001_ITEM | 1 | 72 | 3 | 00:00:01 |
| 14 | NESTED LOOPS | | 1 | 183 | 14 | 00:00:01 |
| 15 | NESTED LOOPS | | 1 | 183 | 14 | 00:00:01 |
| 16 | NESTED LOOPS | | 1 | 104 | 12 | 00:00:01 |
| 17 | NESTED LOOPS | | 1 | 70 | 7 | 00:00:01 |
| 18 | NESTED LOOPS | | 1 | 30 | 4 | 00:00:01 |
| 19 | TABLE ACCESS BY INDEX ROWID | D005_EMPLOYEE | 1 | 18 | 3 | 00:00:01 |
| * 20 | INDEX UNIQUE SCAN | PK_D005 | 1 | | 2 | 00:00:01 |
| 21 | TABLE ACCESS BY INDEX ROWID | D018_SUBSITE | 1 | 12 | 1 | 00:00:01 |
| * 22 | INDEX UNIQUE SCAN | PK_D018 | 1 | | 0 | 00:00:01 |
| 23 | PARTITION RANGE ITERATOR | | 1 | 40 | 3 | 00:00:01 |
| 24 | PARTITION HASH SINGLE | | 1 | 40 | 3 | 00:00:01 |
| * 25 | TABLE ACCESS FULL | F007_RTL_TXN | 1 | 40 | 3 | 00:00:01 |
| * 26 | TABLE ACCESS BY GLOBAL INDEX ROWID BATCHED | F008_RTL_TXN_LI | 1 | 34 | 5 | 00:00:01 |
| * 27 | INDEX RANGE SCAN | IX_F008_RTL_TXN_ID | 7 | | 3 | 00:00:01 |
| * 28 | INDEX UNIQUE SCAN | PK_D001 | 1 | | 1 | 00:00:01 |
| 29 | TABLE ACCESS BY INDEX ROWID | D001_ITEM | 1 | 79 | 2 | 00:00:01 |
| * 30 | TABLE ACCESS BY INDEX ROWID BATCHED | T_OP_MOTIVATION_RATE_MYRTK | 1 | 49 | 7 | 00:00:01 |
| * 31 | INDEX RANGE SCAN | IDX02_CODE_OP_1C | 3 | | 3 | 00:00:01 |
| * 32 | TABLE ACCESS BY INDEX ROWID BATCHED | DET_SALES_PPT_DWH | 1 | 65 | 4 | 00:00:01 |
| * 33 | INDEX RANGE SCAN | IDX_03_RCPT_NUM | 3 | | 2 | 00:00:01 |
----------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 1 - filter("RN">=1 AND "RN"<=10)
* 2 - filter(ROW_NUMBER() OVER ( ORDER BY INTERNAL_FUNCTION("SI"."RECEIPT_DATE") DESC )<=10)
* 10 - filter("F003"."OPERATOR_ID"='000189513' AND "F003"."COST">=TO_NUMBER(TO_CHAR("F003"."COST")) AND "F003"."COST"<=TO_NUMBER(TO_CHAR("F003"."COST")))
* 11 - access("F003"."SUBSITE"='S165' AND "F003"."BUSINESSDAY"=TO_DATE(' 2021-11-23 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
* 11 - filter("F003"."BUSINESSDAY"=TO_DATE(' 2021-11-23 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "F003"."DOC_NUMBER" IS NOT NULL)
* 12 - access("I"."D001_CODE_1C"="F003"."ITEM")
* 12 - filter("I"."D001_CODE_1C" IS NOT NULL)
* 20 - access("E"."EMPLOYEE_ID"=3561503543)
* 22 - access("S"."SUBSITE_ID"=29260)
* 25 - filter("T"."EMPLOYEE_ID"=3561503543 AND "T"."SUBSITE_ID"=29260 AND "T"."F007_TS"<=TO_DATE(' 2021-11-23 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "T"."F007_RCPT_NUM_1C" IS NOT NULL)
* 26 - filter("L"."F008_AMOUNT">=TO_NUMBER(TO_CHAR("L"."F008_AMOUNT")) AND "L"."F008_AMOUNT"<=TO_NUMBER(TO_CHAR("L"."F008_AMOUNT")))
* 27 - access("T"."RTL_TXN_ID"="L"."RTL_TXN_ID")
* 28 - access("L"."ITEM_ID"="I"."ITEM_ID")
* 30 - filter("SI"."SALE_PERIOD"="MR"."MOTIV_RATE_PERIOD"(+))
* 31 - access("SI"."CODE_OP"="MR"."CODE_OP"(+) AND "SI"."VENDOR_CODE"="MR"."CODE_1C"(+))
* 32 - filter("SI"."CODE_OP"="DET"."OP_CODE"(+) AND "SI"."VENDOR_CODE"="DET"."ITEM_ARTICLE"(+) AND "DET"."ITEM_ARTICLE"(+) IS NOT NULL AND "DET"."PERIOD"(+)=TO_NUMBER("SI"."SALE_PERIOD") AND
LTRIM("SI"."OPERATOR_ID",'0')=LTRIM("DET"."TAB_NUM_RTK"(+),'0'))
* 33 - access("SI"."RECEIPT_NUM"="DET"."RCPT_NUM"(+))
* 33 - filter("DET"."RCPT_NUM"(+) IS NOT NULL)
Actual solution
Managed to get procedure execution plan from DBA. The problem was that optimizer chose another index for joining scheme.sales_details table when executing query inside the procedure. Added INDEX HINT with the same index which was used in regular query and everything works just fine.
Deprecated ideas down below
As far as I understood the problem is in Oracle optimizer which "thought" that doing UNION ALL first is better than pushing predicate into the sub-query. Separating this union into two single queries make him push pred without any hesitations.
Probably this can be fixed by playing with hints, that's wip for now.
Temporary workaround is to regroup the query, going from this structure
select *
from (select row_number() rn
, u.*
from (select *
from first_query
union all
select *
from second_query) u
-- some joins
join first_table ft
join second_table st
-- predicate block
where 1=1
and a = b
)
where rn between c and d;
to this
select *
from (select row_number() rn
, u.*
from (select *
from first_query) u
-- some joins
join first_table ft
join second_table st
-- predicate block
where 1=1
and a = b
union all
select row_number() rn
, u.*
from (select *
from second_query) u
-- some joins
join first_table ft
join second_table st
-- predicate block
where 1=1
and a = b
)
where rn between c and d;
That's not the perfect solution cause it doubles the JOIN section but at least it works.

Use Eloquent to Select Latest Row in Each Group Results

I have following data for Example model:
id | object_id | value | updated_at
------------------------------------------------------
1 | 1 | 200 | 2021-04-19 01:00:00
2 | 2 | 1200 | 2021-04-08 01:00:00
3 | 3 | 9000 | 2021-04-07 01:00:00
4 | 1 | 100 | 2021-04-10 01:00:00
5 | 2 | 900 | 2021-04-13 01:00:00
6 | 3 | 8000 | 2021-04-12 01:00:00
I want to get the latest updated rows grouped by object_id, for example:
id | object_id | value | updated_at
------------------------------------------------------
1 | 1 | 200 | 2021-04-19 01:00:00
5 | 2 | 900 | 2021-04-13 01:00:00
6 | 3 | 8000 | 2021-04-12 01:00:00
How can I achieve that result using Eloquent?
do you try?
$users = User::orderBy('updated_at','DESC')
->groupBy('object_id')
->get();

select group by dimension and accumulate column percent

I've using ClickHouse and I have this table
| URL | visits |
| ------------- |:------------- |
| URL1 | 5 |
| URL2 | 30 |
| URL3 | 1 |
| URL4 | 30 |
| URL5 | 9 |
| URL1 | 5 |
| URL2 | 20 |
I can group by url,
select
url,
sum(visits) as visits
from
database.tableVistis
group by
url
| URL | visits |
| ------------- |:------------- |
| URL1 | 10 |
| URL2 | 50 |
| URL3 | 1 |
| URL4 | 30 |
| URL5 | 9 |
And I want this result (group by url, % over total of visits, and % sum accumulate)
| URL | visits | % | Accumulate |
| ------------- |:------------- |----------|------------|
| URL2 | 50 |50% | 50% |
| URL4 | 30 |30% | 80% |
| URL1 | 10 |10% | 90% |
| URL5 | 9 |9% | 99% |
| URL3 | 1 |1% | 100% |
Any idea?
Thanks!!
Try this query:
SELECT result.1 AS URL, result.2 AS visits, round(result.3,2) AS "%", round(result.4, 2) AS Accumulate
FROM (
SELECT
groupArray((URL, visits)) url_visits,
arraySum(x -> x.2, url_visits) total_visits,
arrayMap(x -> (100 / total_visits) * x.2, url_visits) percent_visits,
arrayCumSum(percent_visits) acc_percent_visits,
arrayJoin(arrayMap((x, y, z) -> (x.1, x.2, y, z), url_visits, percent_visits, acc_percent_visits)) result
FROM (
SELECT URL, sum(visits) visits
FROM (
/* test data */
SELECT data.1 URL, data.2 visits
FROM (
SELECT arrayJoin([
('URL1', 5 ),
('URL2', 30),
('URL3', 1 ),
('URL4', 30),
('URL5', 9 ),
('URL1', 5 ),
('URL2', 20)]) data))
GROUP BY URL
ORDER BY visits DESC))
/* result
┌─URL──┬─visits─┬──%─┬─Accumulate─┐
│ URL2 │ 50 │ 50 │ 50 │
│ URL4 │ 30 │ 30 │ 80 │
│ URL1 │ 10 │ 10 │ 90 │
│ URL5 │ 9 │ 9 │ 99 │
│ URL3 │ 1 │ 1 │ 100 │
└──────┴────────┴────┴────────────┘
*/
Yea! Thanks!!
SELECT
result.1 AS URL,
result.2 AS visits,
round(result.3,
2) AS "%",
round(result.4,
2) AS Accumulate
FROM
(
SELECT
groupArray((URL,
visits)) url_visits,
arraySum(x -> x.2,
url_visits) total_visits,
arrayMap(x -> (100 / total_visits) * x.2,
url_visits) percent_visits,
arrayCumSum(percent_visits) acc_percent_visits,
arrayJoin(arrayMap((x,
y,
z) -> (x.1,
x.2,
y,
z),
url_visits,
percent_visits,
acc_percent_visits)) result
FROM
(
SELECT
URL,
sum(visits) visits
FROM
(/* test data */
SELECT
URL,
visits
FROM
(
select
landing as URL,
visitas as visits
from
Analytics
where
fecha > '2019-05-01'))
GROUP BY
URL
ORDER BY
visits DESC))
This query is more compact:
SELECT
result.1 AS URL,
result.2 AS visits,
round(result.3, 2) AS `%`,
round(result.4, 2) AS Accumulate
FROM
(
SELECT
groupArray((URL, visits)) AS url_visits,
arraySum(x -> (x.2), url_visits) AS total_visits,
arrayMap(x -> ((100 / total_visits) * (x.2)), url_visits) AS percent_visits,
arrayCumSum(percent_visits) AS acc_percent_visits,
arrayJoin(arrayMap((x, y, z) -> (x.1, x.2, y, z), url_visits, percent_visits, acc_percent_visits)) AS result
FROM
(
SELECT
landing AS URL,
sum(visitas) AS visits
FROM Analytics
WHERE fecha > '2019-05-01'
GROUP BY URL
ORDER BY visits DESC
)
)

Clickhouse SQL: Reshape data from long format to wide format

I'm using Clickhouse SQL dialect. After array decomposition I have the data in the following format.
|----- |---------------------|----------------|------------------|
| id | timestamp | property_key | property_value |
|----- |---------------------|----------------|------------------|
| 01 | 2019-09-25 16:24:38 | query | Palmera |
|------|---------------------|----------------|------------------|
| 01 | 2019-09-25 16:24:38 | found_items | 10 |
|------|---------------------|----------------|------------------|
| 02 | 2019-09-25 13:11:09 | query | pigeo |
|------|---------------------|----------------|------------------|
| 02 | 2019-09-25 13:11:09 | found_items | 0 |
|------|---------------------|----------------|------------------|
| 03 | 2019-09-25 16:08:13 | query | harmon |
|------|---------------------|----------------|------------------|
| 03 | 2019-09-25 16:08:13 | found_items | 17 |
|------|---------------------|----------------|------------------|
I received such result with a query
SELECT id, timestamp,
properties.key AS property_key,
properties.value as property_value
FROM (
SELECT
rowNumberInAllBlocks() as id,
timestamp,
properties.key,
properties.value
FROM database.table
WHERE timestamp BETWEEN toDateTime('2019-09-16 11:26:56')
AND toDateTime('2019-09-26 11:26:56')
ORDER BY timestamp)
ARRAY JOIN properties
WHERE
properties.key IN ('query', 'found_items')
I need to extract queries whose found_items is equal to 0. I can't get how to reshape data from the long format to wide format. So, the expected result is the following.
|----- |---------------------|-----------------|---------------|
| id | timestamp | query | found_items |
|----- |---------------------|-----------------|---------------|
| 02 | 2019-09-25 13:11:09 | pigeo | 0 |
|------|---------------------|-----------------|---------------|
| 15 | 2019-09-25 16:08:13 | coche | 0 |
|------|---------------------|-----------------|---------------|
| 27 | 2019-09-16 13:19:46 | panitos pampers | 0 |
|------|---------------------|-----------------|---------------|
OR
|----- |---------------------|----------------|------------------|
| id | timestamp | property_key | property_value |
|----- |---------------------|----------------|------------------|
| 02 | 2019-09-25 13:11:09 | query | pigeo |
|------|---------------------|----------------|------------------|
| 15 | 2019-09-25 16:08:13 | query | coche |
|------|---------------------|----------------|------------------|
| 27 | 2019-09-16 13:19:46 | query | panitos pampers |
|------|---------------------|----------------|------------------|
Try this query:
SELECT
id,
groupArray(timestamp)[1] timestamp,
groupArray(properties.key)[1] property_key,
groupArray(properties.value) property_value
FROM (
SELECT
rowNumberInAllBlocks() as id,
timestamp,
properties.key,
properties.value
FROM test.test_011
WHERE timestamp BETWEEN toDateTime('2019-09-16 11:26:56') AND toDateTime('2019-09-26 11:26:56')
AND properties.value[indexOf(properties.key, 'found_items')] = '0'
ORDER BY timestamp)
ARRAY JOIN properties
WHERE properties.key IN ('query' /*, ..*/)
GROUP BY id, properties.key
ORDER BY id
/* Result
┌─id─┬───────────timestamp─┬─property_key─┬─property_value────────┐
│ 0 │ 2019-09-25 13:11:09 │ query │ ['pigeo'] │
│ 1 │ 2019-09-16 13:19:46 │ query │ ['panitos','pampers'] │
└────┴─────────────────────┴──────────────┴───────────────────────┘
*/
/* prepare test data */
CREATE TABLE test.test_011 (
timestamp DateTime,
properties Nested(key String, value String)
) ENGINE = Memory;
INSERT INTO test.test_011
VALUES
(toDateTime('2019-09-25 16:24:38'), ['query', 'found_items'], ['Palmera', '10']),
(toDateTime('2019-09-25 13:11:09'), ['query', 'found_items'], ['pigeo', '0']),
(toDateTime('2019-09-25 16:08:13'), ['query', 'found_items'], ['harmon', '17']),
(toDateTime('2019-09-16 13:19:46'), ['found_items', 'query', 'query'], ['0', 'panitos', 'pampers']),
(toDateTime('2019-09-25 16:22:38'), ['query', 'query'], ['test', 'test']);

Indexes hints in a Subquery

I have a SQL statement that has performance issues.
Adding the following index and a SQL hint to use the index improves the performance 10 fold but I do not understand why.
BUS_ID is part of the primary key(T1.REF is the other part fo the key) and clustered index on the T1 table.
The T1 table has about 100,000 rows. BUS_ID has only 6 different values. Similarly the T1.STATUS column can only have a limited number of
possibilities and the majority of these(99%) will be the same value.
If I run the query without the hint(/*+ INDEX ( T1 T1_IDX1) NO_UNNEST */) it takes 5 seconds and with the hint it takes .5 seconds.
I don't understand how the index helps the subquery as T1.STATUS isn't used in any of the 'where' or 'join' clauses in the subquery.
What am I missing?
SELECT
/*+ NO_UNNEST */
t1.bus_id,
t1.ref,
t2.cust,
t3.cust_name,
t2.po_number,
t1.status_old,
t1.status,
t1.an_status
FROM t1
LEFT JOIN t2
ON t1.bus_id = t2.bus_id
AND t1.ref = t2.ref
JOIN t3
ON t3.cust = t2.cust
AND t3.bus_id = t2.bus_id
WHERE (
status IN ('A', 'B', 'C') AND status_old IN ('X', 'Y'))
AND EXISTS
( SELECT /*+ INDEX ( T1 T1_IDX1) NO_UNNEST */
*
FROM t1
WHERE ( EXISTS ( SELECT /*+ NO_UNNEST */
*
FROM t6
WHERE seq IN ( '0', '2' )
AND t1.bus_id = t6.bus_id)
OR (EXISTS
(SELECT /*+ NO_UNNEST */
*
FROM t6
WHERE seq = '1'
AND (an_status = 'Y'
OR
an_status = 'X')
AND t1.bus_id = t6.bus_id))
AND t2.ref = t1.ref))
AND USER IN ('FRED')
AND ( t2.status != '45'
AND t2.status != '20')
AND NOT EXISTS ( SELECT
/*+ NO_UNNEST */
*
FROM t4
WHERE EXISTS
(
SELECT
/*+ NO_UNNEST */
*
FROM t5
WHERE pd IN ( '1',
'0' )
AND appl = 'RYP'
AND appl_id IN ( 'RL100')
AND t4.id = t5.id)
AND t2.ref = p.ref
AND t2.bus_id = p.bus_id);
Edited to include Explain Plan and index.
Without Index hint
------------------------------------------------------|-------------------------------------
Operation | Options |Cost| # |Bytes | CPU Cost | IO COST
------------------------------------------------------|-------------------------------------
select statement | | 20 | 1 | 211 | 15534188 | 19 |
view | | 20 | 1 | 211 | 15534188 | 19 |
count | | | | | | |
view | | 20 | 1 | 198 | 15534188 | 19 |
sort | ORDER BY | 20 | 1 | 114 | 15534188 | 19 |
nested loops | | 7 | 1 | 114 | 62487 | 7 |
nested loops | | 7 | 1 | 114 | 62487 | 7 |
nested loops | | 6 | 1 | 84 | 53256 | 6 |
inlist iterator | | | | | | |
TABLE access t1 | INDEX ROWID | 4 | 1 | 29 | 36502 | 4 |
index-t1_idx#3 | RANGE SCAN | 3 | 1 | | 28686 | 3 |
TABLE access - t2 | INDEX ROWID | 2 | 1 | 55 | 16754 | 2 |
index t2_idx#0 | UNIQUE SCAN | 1 | 1 | | 9042 | 1 |
filter | | | | | | |
TABLE access-t1 | INDEX ROWID | 2 | 1 | 15 | 7433 | 2 |
TABLE access-t6 | INDEX ROWID | 3 | 1 | 4 | 23169 | 3 |
index-t6_idx#0 | UNIQUE RANGE SCAN | 1 | 3 | | 7721 | 1 |
filter | | | | | | |
TABLE access-t6 | INDEX ROWID | 2 | 2 | 8 | 15363 | 2 |
index-t6_idx#0 | UNIQUE RANGE SCAN | 1 | 3 | | 7521 | 1 |
index-t4_idx#1 | RANGE SCAN | 3 | 1 | 28 | 21584 | 3 |
inlist iterator | | | | | | |
index-t5_idx#1 | RANGE SCAN | 4 | 1 | 24 | 42929 | 4 |
index-t3_idx#0 | INDEX UNIQUE SCAN | 0 | 1 | | 1900 | 0 |
TABLE access-t3 | INDEX ROWID | 1 | 1 | 30 | 9231 | 1 |
--------------------------------------------------------------------------------------------
With Index hint
------------------------------------------------------|-------------------------------------
Operation | Options |Cost| # |Bytes | CPU Cost | IO COST
------------------------------------------------------|-------------------------------------
select statement | | 21 | 1 | 211 | 15549142 | 19 |
view | | 21 | 1 | 211 | 15549142 | 19 |
count | | | | | | |
view | | 21 | 1 | 198 | 15549142 | 19 |
sort | ORDER BY | 21 | 1 | 114 | 15549142 | 19 |
nested loops | | 7 | 1 | 114 | 62487 | 7 |
nested loops | | 7 | 1 | 114 | 62487 | 7 |
nested loops | | 6 | 1 | 84 | 53256 | 6 |
inlist iterator | | | | | | |
TABLE access t1 | INDEX ROWID | 4 | 1 | 29 | 36502 | 4 |
index-t1_idx#3 | RANGE SCAN | 3 | 1 | | 28686 | 3 |
TABLE access - t2 | INDEX ROWID | 2 | 1 | 55 | 16754 | 2 |
index t2_idx#0 | UNIQUE SCAN | 1 | 1 | | 9042 | 1 |
filter | | | | | | |
TABLE access-t1 | INDEX ROWID | 3 | 1 | 15 | 22387 | 2 |
index-t1_idx#1 | FULL SCAN | 2 |97k| | 14643 | |
TABLE access-t6 | INDEX ROWID | 3 | 1 | 4 | 23169 | 3 |
index-t6_idx#0 | UNIQUE RANGE SCAN | 1 | 3 | | 7721 | 1 |
filter | | | | | | |
TABLE access-t6 | INDEX ROWID | 2 | 2 | 8 | 15363 | 2 |
index-t6_idx#0 | UNIQUE RANGE SCAN | 1 | 3 | | 7521 | 1 |
index-t4_idx#1 | RANGE SCAN | 3 | 1 | 28 | 21584 | 3 |
inlist iterator | | | | | | |
index-t5_idx#1 | RANGE SCAN | 4 | 1 | 24 | 42929 | 4 |
index-t3_idx#0 | INDEX UNIQUE SCAN | 0 | 1 | | 1900 | 0 |
TABLE access-t3 | INDEX ROWID | 1 | 1 | 30 | 9231 | 1 |
--------------------------------------------------------------------------------------------
Table Index
CREATE INDEX T1_IDX#1 ON T1 (BUS_ID, STATUS)

Resources