I had a task to get specific accounts and transactions based on few rules. It's worth noting that accounts and transactions are in different tables and my query returns mostly accounts - proportions are around 70 accounts to 1 transaction. I wanted to get them in one query for convenience sake - it's a stage in bigger process.
Original query:
SELECT DISTINCT
CASE
WHEN (a.transaction_type IN ('500', '501', '502', '920') AND a.transaction_date >= '#DATE#' AND to_char(a.transaction_date,'HH24') >= 16) THEN 'Transaction time'
WHEN b.closing_date >= '#DATE#' THEN 'Closing time'
WHEN b.opening_date >= '#DATE#' THEN 'Opening time'
WHEN (b.type = 'X' AND b.active = 'NO') THEN 'Frozen account'
END AS "comment"
,b.branch
,b.basic
,b.lmt
FROM
VDS.transactions a
JOIN VDS.accounts b ON a.acct_no = b.acct_no
WHERE
(a.transaction_type IN ('500', '501', '502', '920')
AND a.transaction_date >= '#DATE#'
AND to_char(a.transaction_date,'HH24') >= 16)
OR
(b.closing_date >= '#DATE#'
OR b.opening_date >= '#DATE#'
OR (b.type = 'X' AND b.active = 'NO'))
It seemed to work fine even if somewhat sluggish - its execution time was usually somewhere around 12s. Problem is - sometimes it wouldn't finish at all. It looked like the database got completely stuck on the query. Since I'm not an Oracle admin I can't confirm my suspicion that it's this query's fault but multiple tests suggest that it indeed is.
So I have prepared another variant, taking into account that transactions are way less numerous than accounts.
Variant with subquery:
SELECT
'Transaction time' AS "comment"
,b.branch
,b.basic
,b.lmt
FROM
VDS.transactions a
JOIN VDS.accounts b ON a.acct_no = b.acct_no
WHERE
a.transaction_type IN ('500', '501', '502', '920')
AND a.transaction_date >= '#DATE#'
AND to_char(a.transaction_date,'HH24') >= 16
UNION
SELECT
CASE
WHEN closing_date >= '#DATE#' THEN 'Closing time'
WHEN opening_date >= '#DATE#' THEN 'Opening time'
WHEN (type = 'X' AND active = 'NO') THEN 'Frozen account'
END AS "comment"
,branch
,basic
,lmt
FROM
VDS.accounts
WHERE
closing_date >= '#DATE#'
OR opening_date >= '#DATE#'
OR (type = 'X' AND active = 'NO'))
Lo and behold - execution times were reduced to around 3-5s and query no longer blocked database. It also returned slightly more results which is strange but not a problem.
So my final question is: Can someone explain to me what might've been going in the guts of database that it happily accepted variant with subquery while getting erratic with original one? I can understand better performance with subquery but I have no idea why query would sometimes work and sometimes hang up entirely.