Understanding performance of a complex SQL JOIN - performance

I'm trying to understand a performance issue I solved on an SQLite database by restructuring the query.
The task of the query is to filter a list of the latest revisions of protocols. Additionally some protocols may not be released, this are to be excluded from the search. The tables are modelled as follows:
-- Describe PROTOCOL
CREATE TABLE protocol (
id CHAR(36) NOT NULL,
revision CHAR(36) NOT NULL,
timestamp DATETIME,
name TEXT,
PRIMARY KEY (revision)
)
-- Describe PROTOCOLSTATUS
CREATE TABLE protocolstatus (
uuid CHAR(36) NOT NULL,
status TEXT,
timestamp DATETIME,
protocol_id CHAR(36) NOT NULL,
PRIMARY KEY (uuid),
FOREIGN KEY(protocol_id) REFERENCES protocol (revision)
)
The number of entries in protocolstatus can be expected to be some constant times the number entries in protocol (#p), even though over time that constant may become largish.
In a database with 300 protocols and 900 statuses the slower query took about 4 seconds to execute. I also noticed, that if I don't use distinct, the results are duplicated numerous times.
Restructuring the query using a subquery sped the whole thing up to feasible response times (<0.05s).
So how do I approach analyzing what went wrong here, having little formal training in databases? Can I analyze query complexity the way I would analyze algorithms, using Big-O-notation, if I assume that I am searching in linear time (no indizes defined)?
Analyzing the first query that way I notice that it describes a product of four sets with O(#p) entries. So can I assume that the complexity of this query is O(#p^4)?
Analyzing the second query the same way I notice that the outermost-layer describes a product of three sets with O(#p) entries. The second join is against a subquery for which I would arrive at a complexity of O(#p^2), so is the complexity of the whole query = O(#p^3) + O(#p^2) = O(#p^3)?
Is this a legitimate way to evaluate the performance of these queries?
The slower query used to retrieve the list of protocols was:
-- slow query: O((#p)^4) ?, Run Time: real 4.335 user 4.331110 sys 0.005220
SELECT DISTINCT
protocol.id AS protocol_id,
protocol.revision AS protocol_revision,
protocol.timestamp AS protocol_timestamp
FROM
protocolstatus, -- O(#p) |
protocol -- O(#p) | => O(#p^2) entries
JOIN (
SELECT
protocol.id AS id, max(protocol.timestamp) AS ts_max
FROM protocol
GROUP BY protocol.id
) AS anon_1 -- O(#p)
ON protocol.timestamp = anon_1.ts_max
JOIN (
SELECT
max(protocolstatus.timestamp) AS max_1,
protocolstatus.protocol_id AS protocol_id
FROM protocolstatus
GROUP BY protocolstatus.protocol_id
) AS anon_2 -- O(#p)
ON protocol.revision = anon_2.protocol_id
WHERE
protocolstatus.status = 'approved'
AND lower(protocol.name) LIKE lower('%c%')
ORDER BY protocol.name;
The faster query used to retrieve the list of protocols was:
-- fast query: O(#p^3)? Run Time: real 0.042 user 0.041540 sys 0.000767
SELECT
protocol.id AS protocol_id,
protocol.revision AS protocol_revision,
protocol.timestamp AS protocol_timestamp
FROM protocol -- O(#p)
JOIN (
SELECT
protocol.id AS id,
max(protocol.timestamp) AS ts_max
FROM protocol
GROUP BY protocol.id
) AS anon_1 -- query: O(#p), results: O(#p)
ON protocol.timestamp = anon_1.ts_max
JOIN (
SELECT
protocolstatus.protocol_id AS protocol_id,
protocolstatus.status AS status,
protocolstatus.timestamp AS timestamp
FROM protocolstatus -- O(#p)
JOIN (
SELECT
max(protocolstatus.timestamp) AS timestamp,
protocolstatus.protocol_id AS protocol_id
FROM protocolstatus
GROUP BY protocolstatus.protocol_id
) AS anon_3 -- O(#p)
ON protocolstatus.timestamp = anon_3.timestamp
WHERE protocolstatus.status = "approved"
) AS anon_2 -- query: O(#p^2), results: O(#p)
ON protocol.revision = anon_2.protocol_id
WHERE lower(protocol.name) LIKE lower("%c%") ORDER BY protocol.name;
Running EXPLAIN on the queries gives me:
for the slow query:
0|Trace|0|0|0||00|
1|Integer|48|1|0||00|
2|Once|0|48|0||00|
3|OpenEphemeral|2|2|0||00|
4|Noop|0|0|0||00|
5|Integer|0|6|0||00|
6|Integer|0|5|0||00|
7|Null|0|9|9||00|
8|Gosub|8|44|0||00|
9|Goto|0|161|0||00|
10|OpenRead|3|18|0|3|00|
11|OpenRead|7|21|0|k(2,B,B)|00|
12|Rewind|7|29|11|0|00|
13|IdxRowid|7|11|0||00|
14|Seek|3|11|0||00|
15|Column|7|0|10||00|
16|Compare|9|10|1|k(1,B)|00|
17|Jump|18|22|18||00|
18|Move|10|9|0||00|
19|Gosub|7|35|0||00|
20|IfPos|6|48|0||00|
21|Gosub|8|44|0||00|
22|Column|3|2|12||00|
23|CollSeq|13|0|0|(BINARY)|00|
24|AggStep|0|12|3|max(1)|01|
25|If|13|27|0||00|
26|Column|7|0|2||00|
27|Integer|1|5|0||00|
28|Next|7|13|0||01|
29|Close|3|0|0||00|
30|Close|7|0|0||00|
31|Gosub|7|35|0||00|
32|Goto|0|48|0||00|
33|Integer|1|6|0||00|
34|Return|7|0|0||00|
35|IfPos|5|37|0||00|
36|Return|7|0|0||00|
37|AggFinal|3|1|0|max(1)|00|
38|SCopy|2|14|0||00|
39|SCopy|3|15|0||00|
40|MakeRecord|14|2|11||00|
41|NewRowid|2|16|0||00|
42|Insert|2|11|16||08|
43|Return|7|0|0||00|
44|Null|0|2|0||00|
45|Null|0|4|0||00|
46|Null|0|3|0||00|
47|Return|8|0|0||00|
48|Return|1|0|0||00|
49|Integer|100|17|0||00|
50|Once|1|100|0||00|
51|OpenEphemeral|4|2|0||00|
52|SorterOpen|8|3|0|k(1,B)|00|
53|Integer|0|22|0||00|
54|Integer|0|21|0||00|
55|Null|0|25|25||00|
56|Gosub|24|96|0||00|
57|OpenRead|5|24|0|4|00|
58|Rewind|5|65|0||00|
59|Column|5|3|27||00|
60|Sequence|8|28|0||00|
61|Column|5|2|29||00|
62|MakeRecord|27|3|30||00|
63|SorterInsert|8|30|0||00|
64|Next|5|59|0||01|
65|Close|5|0|0||00|
66|OpenPseudo|9|30|3||00|
67|SorterSort|8|100|0||00|
68|SorterData|8|30|0||00|
69|Column|9|0|26||20|
70|Compare|25|26|1|k(1,B)|00|
71|Jump|72|76|72||00|
72|Move|26|25|0||00|
73|Gosub|23|87|0||00|
74|IfPos|22|100|0||00|
75|Gosub|24|96|0||00|
76|Column|9|2|27||00|
77|CollSeq|31|0|0|(BINARY)|00|
78|AggStep|0|27|18|max(1)|01|
79|If|31|81|0||00|
80|Column|9|0|19||00|
81|Integer|1|21|0||00|
82|SorterNext|8|68|0||00|
83|Gosub|23|87|0||00|
84|Goto|0|100|0||00|
85|Integer|1|22|0||00|
86|Return|23|0|0||00|
87|IfPos|21|89|0||00|
88|Return|23|0|0||00|
89|AggFinal|18|1|0|max(1)|00|
90|SCopy|18|32|0||00|
91|SCopy|19|33|0||00|
92|MakeRecord|32|2|34||00|
93|NewRowid|4|35|0||00|
94|Insert|4|34|35||08|
95|Return|23|0|0||00|
96|Null|0|19|0||00|
97|Null|0|20|0||00|
98|Null|0|18|0||00|
99|Return|24|0|0||00|
100|Return|17|0|0||00|
101|SorterOpen|10|3|0|k(1,B)|00|
102|OpenEphemeral|11|0|0|k(3,B,B,B)|08|
103|OpenRead|0|24|0|2|00|
104|OpenRead|1|18|0|5|00|
105|OpenRead|12|19|0|k(1,B)|00|
106|Once|2|114|0||00|
107|OpenAutoindex|13|2|0|k(2,B,B)|00|
108|Rewind|0|114|0||00|
109|Column|0|1|37||00|
110|Rowid|0|38|0||00|
111|MakeRecord|37|2|36|ad|00|
112|IdxInsert|13|36|0||10|
113|Next|0|109|0||03|
114|String8|0|39|0|approved|00|
115|SeekGe|13|147|39|1|00|
116|IdxGE|13|147|39|1|01|
117|Rewind|4|146|0||00|
118|Column|4|1|40||00|
119|IsNull|40|145|0||00|
120|SeekGe|12|145|40|1|00|
121|IdxGE|12|145|40|1|01|
122|IdxRowid|12|36|0||00|
123|Seek|1|36|0||00|
124|Column|1|4|37||00|
125|Function|0|37|43|lower(1)|01|
126|Function|1|42|41|like(2)|02|
127|IfNot|41|145|1||00|
128|Rewind|2|145|0||00|
129|Column|1|2|41||00|
130|Column|2|1|44||00|
131|Ne|44|144|41|(BINARY)|6b|
132|Column|1|0|45||00|
133|Column|12|0|46||00|
134|Column|1|2|47||00|
135|Found|11|144|45|3|00|
136|MakeRecord|45|3|44||00|
137|IdxInsert|11|44|0||00|
138|MakeRecord|45|3|44||00|
139|Column|1|4|48||00|
140|Sequence|10|49|0||00|
141|Move|44|50|0||00|
142|MakeRecord|48|3|41||00|
143|SorterInsert|10|41|0||00|
144|Next|2|129|0||01|
145|Next|4|118|0||01|
146|Next|13|116|0||00|
147|Close|1|0|0||00|
148|Close|12|0|0||00|
149|OpenPseudo|14|44|3||00|
150|OpenPseudo|15|51|3||00|
151|SorterSort|10|159|0||00|
152|SorterData|10|51|0||00|
153|Column|15|2|44||20|
154|Column|14|0|45||20|
155|Column|14|1|46||00|
156|Column|14|2|47||00|
157|ResultRow|45|3|0||00|
158|SorterNext|10|152|0||00|
159|Close|14|0|0||00|
160|Halt|0|0|0||00|
161|Transaction|0|0|0||00|
162|VerifyCookie|0|29|0||00|
163|TableLock|0|18|0|protocol|00|
164|TableLock|0|24|0|protocolstatus|00|
165|String8|0|52|0|%c%|00|
166|Function|1|52|42|lower(1)|01|
167|Goto|0|10|0||00|
for the fast query:
0|Trace|0|0|0||00|
1|Integer|48|1|0||00|
2|Once|0|48|0||00|
3|OpenEphemeral|1|2|0||00|
4|Noop|0|0|0||00|
5|Integer|0|6|0||00|
6|Integer|0|5|0||00|
7|Null|0|9|9||00|
8|Gosub|8|44|0||00|
9|Goto|0|163|0||00|
10|OpenRead|2|18|0|3|00|
11|OpenRead|8|21|0|k(2,B,B)|00|
12|Rewind|8|29|11|0|00|
13|IdxRowid|8|11|0||00|
14|Seek|2|11|0||00|
15|Column|8|0|10||00|
16|Compare|9|10|1|k(1,B)|00|
17|Jump|18|22|18||00|
18|Move|10|9|0||00|
19|Gosub|7|35|0||00|
20|IfPos|6|48|0||00|
21|Gosub|8|44|0||00|
22|Column|2|2|12||00|
23|CollSeq|13|0|0|(BINARY)|00|
24|AggStep|0|12|3|max(1)|01|
25|If|13|27|0||00|
26|Column|8|0|2||00|
27|Integer|1|5|0||00|
28|Next|8|13|0||01|
29|Close|2|0|0||00|
30|Close|8|0|0||00|
31|Gosub|7|35|0||00|
32|Goto|0|48|0||00|
33|Integer|1|6|0||00|
34|Return|7|0|0||00|
35|IfPos|5|37|0||00|
36|Return|7|0|0||00|
37|AggFinal|3|1|0|max(1)|00|
38|SCopy|2|14|0||00|
39|SCopy|3|15|0||00|
40|MakeRecord|14|2|11||00|
41|NewRowid|1|16|0||00|
42|Insert|1|11|16||08|
43|Return|7|0|0||00|
44|Null|0|2|0||00|
45|Null|0|4|0||00|
46|Null|0|3|0||00|
47|Return|8|0|0||00|
48|Return|1|0|0||00|
49|Gosub|1|2|0||00|
50|Integer|101|17|0||00|
51|Once|1|101|0||00|
52|OpenEphemeral|5|2|0||00|
53|SorterOpen|9|3|0|k(1,B)|00|
54|Integer|0|22|0||00|
55|Integer|0|21|0||00|
56|Null|0|25|25||00|
57|Gosub|24|97|0||00|
58|OpenRead|6|24|0|4|00|
59|Rewind|6|66|0||00|
60|Column|6|3|27||00|
61|Sequence|9|28|0||00|
62|Column|6|2|29||00|
63|MakeRecord|27|3|30||00|
64|SorterInsert|9|30|0||00|
65|Next|6|60|0||01|
66|Close|6|0|0||00|
67|OpenPseudo|10|30|3||00|
68|SorterSort|9|101|0||00|
69|SorterData|9|30|0||00|
70|Column|10|0|26||20|
71|Compare|25|26|1|k(1,B)|00|
72|Jump|73|77|73||00|
73|Move|26|25|0||00|
74|Gosub|23|88|0||00|
75|IfPos|22|101|0||00|
76|Gosub|24|97|0||00|
77|Column|10|2|27||00|
78|CollSeq|31|0|0|(BINARY)|00|
79|AggStep|0|27|18|max(1)|01|
80|If|31|82|0||00|
81|Column|10|0|19||00|
82|Integer|1|21|0||00|
83|SorterNext|9|69|0||00|
84|Gosub|23|88|0||00|
85|Goto|0|101|0||00|
86|Integer|1|22|0||00|
87|Return|23|0|0||00|
88|IfPos|21|90|0||00|
89|Return|23|0|0||00|
90|AggFinal|18|1|0|max(1)|00|
91|SCopy|18|32|0||00|
92|SCopy|19|33|0||00|
93|MakeRecord|32|2|34||00|
94|NewRowid|5|35|0||00|
95|Insert|5|34|35||08|
96|Return|23|0|0||00|
97|Null|0|19|0||00|
98|Null|0|20|0||00|
99|Null|0|18|0||00|
100|Return|24|0|0||00|
101|Return|17|0|0||00|
102|SorterOpen|11|3|0|k(1,B)|00|
103|OpenRead|4|24|0|4|00|
104|OpenRead|0|18|0|5|00|
105|OpenRead|12|19|0|k(1,B)|00|
106|Once|2|116|0||00|
107|OpenAutoindex|13|4|0|k(4,B,B,B,B)|00|
108|Rewind|4|116|0||00|
109|Column|4|1|37||00|
110|Column|4|2|38||00|
111|Column|4|3|39||00|
112|Rowid|4|40|0||00|
113|MakeRecord|37|4|36|acad|00|
114|IdxInsert|13|36|0||10|
115|Next|4|109|0||03|
116|String8|0|41|0|approved|00|
117|SeekGe|13|149|41|1|00|
118|IdxGE|13|149|41|1|01|
119|Column|13|2|42||00|
120|IsNull|42|148|0||00|
121|SeekGe|12|148|42|1|00|
122|IdxGE|12|148|42|1|01|
123|IdxRowid|12|36|0||00|
124|Seek|0|36|0||00|
125|Column|0|4|37||00|
126|Function|0|37|45|lower(1)|01|
127|Function|1|44|43|like(2)|02|
128|IfNot|43|148|1||00|
129|Rewind|1|148|0||00|
130|Column|0|2|43||00|
131|Column|1|1|46||00|
132|Ne|46|147|43|(BINARY)|6b|
133|Rewind|5|147|0||00|
134|Column|13|1|47||00|
135|Column|5|0|48||00|
136|Ne|48|146|47|(BINARY)|6b|
137|Column|0|0|49||00|
138|Column|12|0|50||00|
139|Column|0|2|51||00|
140|MakeRecord|49|3|48||00|
141|Column|0|4|38||00|
142|Sequence|11|39|0||00|
143|Move|48|40|0||00|
144|MakeRecord|38|3|47||00|
145|SorterInsert|11|47|0||00|
146|Next|5|134|0||01|
147|Next|1|130|0||01|
148|Next|13|118|0||00|
149|Close|0|0|0||00|
150|Close|12|0|0||00|
151|OpenPseudo|14|48|3||00|
152|OpenPseudo|15|52|3||00|
153|SorterSort|11|161|0||00|
154|SorterData|11|52|0||00|
155|Column|15|2|48||20|
156|Column|14|0|49||20|
157|Column|14|1|50||00|
158|Column|14|2|51||00|
159|ResultRow|49|3|0||00|
160|SorterNext|11|154|0||00|
161|Close|14|0|0||00|
162|Halt|0|0|0||00|
163|Transaction|0|0|0||00|
164|VerifyCookie|0|29|0||00|
165|TableLock|0|18|0|protocol|00|
166|TableLock|0|24|0|protocolstatus|00|
167|String8|0|53|0|%c%|00|
168|Function|1|53|44|lower(1)|01|
169|Goto|0|10|0||00|

Related

Is there any approach to increasing the performance of below query?

The below query is returning almost 800k records for period Sep-21 with all account and LOB
and is taking 9+hrs to generate a report.
the code is pretty straight forward. When tried with individual queries, i.e, inline and outer query, it was taking less time (Individual), but when i join those 2 query with the condition
AND gl.gl_sl_link_table (+) =XAL.gl_sl_link_table
AND gl.gl_sl_link_id (+) =XAL.gl_sl_link_id
this was taking time.
Is there any approach to modify this query, such that overall performance is increased?
SELECT
XAH.AE_HEADER_ID,
XAH.APPLICATION_ID,
XAH.LEDGER_ID,
XAH.ENTITY_ID,
XAH.EVENT_ID,
XAH.EVENT_TYPE_CODE,
XAH.ACCOUNTING_DATE,
XAH.GL_TRANSFER_STATUS_CODE,
XAH.GL_TRANSFER_DATE,
XAH.JE_CATEGORY_NAME,
XAH.ACCOUNTING_BATCH_ID,
XAH.PERIOD_NAME,
XAH.LEGAL_ENTITY_ID,
XAH.DESCRIPTION,
XAL.ENTERED_DR,
XAL.ENTERED_CR,
XAL.ACCOUNTED_CR,
XAL.ACCOUNTED_DR,
XAL.CURRENCY_CONVERSION_RATE,
XAL.CURRENCY_CONVERSION_DATE,
XAL.CURRENCY_CODE,
XAL.CURRENCY_CONVERSION_TYPE,
XAL.CODE_COMBINATION_ID,
XAL.DESCRIPTION DESCRIPTION1,
XASV.SEGMENT_VALUE ,
XASV.SEGMENT_TYPE_CODE,
GCC.SEGMENT1,
GCC.SEGMENT2,
GCC.SEGMENT3,
GCC.SEGMENT4,
GCC.SEGMENT5,
GCC.SEGMENT6,
GCC.SEGMENT7,
pbe.sourceref "SOURCE_REFERENCE",
gl.name AS "BATCH_NAME",
DECODE(gl.status, 'P', 'Posted', 'U', 'UnPosted', gl.status) AS "BATCH_STATUS"
FROM
XLA_AE_HEADERS XAH,
XLA_AE_LINES XAL,
XLA_AE_SEGMENT_VALUES XASV,
GL_CODE_COMBINATIONS GCC,
pjb_rev_distributions prd,
pjb_billing_events pbe,
(
SELECT
gir.gl_sl_link_table,
gir.gl_sl_link_id,
gjb.name,
gjb.status
FROM
gl_import_references gir,
gl_je_batches gjb,
gl_je_headers gjh,
gl_je_lines gjl
,GL_ledgers gl
WHERE
1 = 1
AND gjh.je_header_id = gir.je_header_id
AND gjl.je_line_num = gir.je_line_num
AND gjh.je_batch_id = gjb.je_batch_id
AND gjh.je_header_id = gjl.je_header_id
AND gjl.je_line_num = gir.je_line_num
and gjh.ledger_id =gl.ledger_id
and gl.LEDGER_CATEGORY_CODE = 'PRIMARY'
) gl
WHERE
XAH.AE_HEADER_ID=XAL.AE_HEADER_ID
AND XAH.APPLICATION_ID='10036'
AND XAH.EVENT_TYPE_CODE in ('IP_REVENUE','EX_REVENUE','IP_REVENUE_ADJ','EX_REVENUE_ADJ')
AND XAH.PERIOD_NAME = (:PERIOD_NAME)
AND XASV.AE_HEADER_ID(+)=XAL.AE_HEADER_ID
and XAL.CODE_COMBINATION_ID=GCC.CODE_COMBINATION_ID
AND (GCC.SEGMENT2 IN (:ACCOUNT) OR 'All' IN (:ACCOUNT || 'All'))
AND (GCC.SEGMENT5 IN (:LOB) OR 'All' IN (:LOB || 'All'))
AND XAH.event_id = prd.sla_event_id (+)
AND prd.transaction_id = pbe.event_id (+)
AND gl.gl_sl_link_table (+) =XAL.gl_sl_link_table
AND gl.gl_sl_link_id (+) =XAL.gl_sl_link_id
SQL Explain plan

QlikSense Script Issue : I'm getting multiple records for some Casenumbers with different state like " Progress' & "On Hold"

LOAD
number as [Case Number],
number as key_case,
short_description as Description,
ApplyMap('map_CustomerDeliveryGroup',dv_company,'N/A') as CustomerGroupNo,
mid(dv_priority,5) as Priority,
dv_business_service as Service,
dv_state as State,
dv_category as ServiceCI,
DATE(SUBFIELD(sys_created_on,' ',1)) as key_reported_date,
IF(DATE(SUBFIELD(sys_created_on,' ',1)) > monthstart(today()-360),'1','0') as InYear,
text(applymap('map_wanted_customers',upper(dv_company),0)) as WantedCustomer,
contact_type,
dv_contact as contact,
dv_company as Customer,
dv_assignment_group as Assigned_Group,
dv_assigned_to as Assignee
FROM [lib];
dv_task as key_case,
dv_stage as ResponseStage,
business_percentage as ResponseLeft,
IF(business_percentage <= 100, 'Met','Missed') as SLA_Response_MeasurementStatus_Name,
DATE(SUBFIELD(end_time ,' ',1)) as ResponseTime
FROM [lib]
WHERE wildmatch(dv_sla,'*Response*')
and exists([Case Number],dv_task)
and dv_stage = 'Completed';
your table probably contains records from different stage of case, something like log,
there is second table with key_case which makes joins and it can also affect data,
it is really hard to give exact answer without seeing data model/data or just qvw file

MERGE into getting stuck all of a sudden

I have a stored procedure that is getting stuck on the merge into all of a sudden but has been working fine for years. Any advice ? The SP is in Oracle SQL developer and it is being executed in a Visual Studios SSIS package
Query below:
MERGE INTO CORE_APPT C
USING (
SELECT DISTINCT
TST_TKR_ID,
TST_TKR_ID_SRC,
APPT_ID_SRC,
APPT_CRETN_DTE,
APNTMT_DT,
ETS_APNTMT_ID,
ETS_TST_CNTR,
TST_STS_TYP_DESC,
APPT_STS_TYP,
TST_DLVR_MTHD_TYP_CDE,
DLVR_GRP_TYP,
TST_LNCH_TM,
TRNSCTN_ID,
TST_PKG_ID,
RND_TRIP_TST_FLG,
UPDT_DTE_TM,
PROD_ID,
ACTN_DTE_TM,
TST_DURN,
BRKRG_APPT_UPDT_DTM,
TST_APPT_TYP_CDE,
CNCL_MKUP_RSN_TYP,
DLNQNT_HLD_FLG,
TST_TKR_TST_UPDT_DTE_TM,
SCR_HLD_LVL_TYP_CDE,
SCR_CNCL_FLG,
ETS_CANDTE_SCR_HLD_FLG,
TST_CNTR_HLD_FLG,
TST_ADM_HLD_FLG,
ETS_SCR_CNCL_FLG,
TST_ADM_HLD_RSN_CDE,
TST_CNTR_HLD_RSN_CDE,
ETS_CANDTE_SCR_HLD_RSN_CDE,
ETS_SCR_CNCL_RSN_CDE,
DLNQNT_HLD_RSN_CDE,
TST_TKR_SCR_STS_TYP_CDE,
TST_TKR_SCR_STS_RSN_TYP_CDE,
PYMT_NO,
DATA_SRCE AS DATA_SRCE,
CURRENT_FLAG,
PRGRM_TYP,
sysdate as RCD_CRTD_DTE,
user as RCD_CRTD_USER,
REG_SYS_ID AS REG_SYS_ID,
TST_NAM AS TST_NAM,
CNTRY_SETL_RSP AS CNTRY_SETL_RSP
FROM STG_CMMN_APPT A
WHERE A.CURRENT_FLAG = 'Y'
) S
ON (C.APPT_ID_SRC = S.APPT_ID_SRC
AND C.REG_SYS_ID = S.REG_SYS_ID
AND C.DATA_SRCE = S.DATA_SRCE) -- added in EREG4.0 changes
WHEN MATCHED THEN UPDATE
SET C.CURRENT_FLAG = 'N'
WHERE C.CURRENT_FLAG = 'Y'
WHEN NOT MATCHED THEN INSERT
(
C.TST_TKR_ID,
C.TST_TKR_ID_SRC,
C.APPT_ID_SRC,
C.APPT_CRETN_DTE,
C.APNTMT_DT,
C.ETS_APNTMT_ID,
C.TST_CNTR_ID_SRC,
C.TST_STS_TYP_DESC,
C.APPT_STS_TYP,
C.TST_DLVR_MTHD_TYP_CDE,
C.DLVR_GRP_TYP,
C.TST_LNCH_TM,
C.TRNSCTN_ID,
C.TST_PKG_ID,
C.RND_TRIP_TST_FLG,
C.UPDT_DTE_TM,
C.PROD_ID,
C.ACTN_DTE_TM,
C.TST_DURN,
C.BRKRG_APPT_UPDT_DTM,
C.TST_APPT_TYP_CDE,
C.CNCL_MKUP_RSN_TYP,
C.DLNQNT_HLD_FLG,
C.TST_TKR_TST_UPDT_DTE_TM,
C.SCR_HLD_LVL_TYP_CDE,
C.SCR_CNCL_FLG,
C.ETS_CANDTE_SCR_HLD_FLG,
C.TST_CNTR_HLD_FLG,
C.TST_ADM_HLD_FLG,
C.ETS_SCR_CNCL_FLG,
C.TST_ADM_HLD_RSN_CDE,
C.TST_CNTR_HLD_RSN_CDE,
C.ETS_CANDTE_SCR_HLD_RSN_CDE,
C.ETS_SCR_CNCL_RSN_CDE,
C.DLNQNT_HLD_RSN_CDE,
C.TST_TKR_SCR_STS_TYP_CDE,
C.TST_TKR_SCR_STS_RSN_TYP_CDE,
C.PYMT_NO,
C.DATA_SRCE,
C.CURRENT_FLAG,
C.PGM_TYP,
C.RCD_CRTD_DTE,
C.RCD_CRTD_USER,
C.REG_SYS_ID,
C.TST_NAM,
C.CNTRY_SETL_RSP
)
VALUES
(
S.TST_TKR_ID,
S.TST_TKR_ID_SRC,
S.APPT_ID_SRC,
S.APPT_CRETN_DTE,
S.APNTMT_DT,
S.ETS_APNTMT_ID,
S.ETS_TST_CNTR,
S.TST_STS_TYP_DESC,
S.APPT_STS_TYP,
S.TST_DLVR_MTHD_TYP_CDE,
S.DLVR_GRP_TYP,
S.TST_LNCH_TM,
S.TRNSCTN_ID,
S.TST_PKG_ID,
S.RND_TRIP_TST_FLG,
S.UPDT_DTE_TM,
S.PROD_ID,
S.ACTN_DTE_TM,
S.TST_DURN,
S.BRKRG_APPT_UPDT_DTM,
S.TST_APPT_TYP_CDE,
S.CNCL_MKUP_RSN_TYP,
S.DLNQNT_HLD_FLG,
S.TST_TKR_TST_UPDT_DTE_TM,
S.SCR_HLD_LVL_TYP_CDE,
S.SCR_CNCL_FLG,
S.ETS_CANDTE_SCR_HLD_FLG,
S.TST_CNTR_HLD_FLG,
S.TST_ADM_HLD_FLG,
S.ETS_SCR_CNCL_FLG,
S.TST_ADM_HLD_RSN_CDE,
S.TST_CNTR_HLD_RSN_CDE,
S.ETS_CANDTE_SCR_HLD_RSN_CDE,
S.ETS_SCR_CNCL_RSN_CDE,
S.DLNQNT_HLD_RSN_CDE,
S.TST_TKR_SCR_STS_TYP_CDE,
S.TST_TKR_SCR_STS_RSN_TYP_CDE,
S.PYMT_NO,
S.DATA_SRCE,
S.CURRENT_FLAG,
S.PRGRM_TYP,
S.RCD_CRTD_DTE,
S.RCD_CRTD_USER,
S.REG_SYS_ID,
S.TST_NAM,
S.CNTRY_SETL_RSP
)
;
TIA!

Oracle Apex Reports shows data of different user

I am working on Oracle Apex and not that familiar with it. The application I am working on has already been developed by some other developer who has left the company. The issue is - There is a main/super user with which the actual db connection is made (using DADS.conf file entry). After that, user is presented with a Login screen where he enters db subuser credentials. We have few application level contexts defined, so after subuser login we set the context like username for that subuser. In the application there is a report that is supposed to show data for logged in subuser. Now, when first user logs in, the reports shows correct data. When second user logs in from a different machine report starts showing data for the second user in both the application instances. Sometimes second user's report shows data for first user. This behavior is random. Apart from the report other application works fine. I seems that Apex in this case is using same physical database connection and hence the contexts are getting overwritten. I might be wrong here. I am very confused and unable to find any solution. Any help is appreciated.
Here is the report query (much complicated) -
With
Date_range as (
select * from X_LOHAC_DateRANGE_WK
)
--
,Haud_a
AS ( select wor_works_order_no haud_pk_id, WOR_CHAR_ATTRIB110 HAUD_NEW_VALUE, WOR_DATE_ATTRIB131 HAUD_TIMESTAMP
from work_orders
where 1=1
AND WOR_CHAR_ATTRIB110 in ('REV', 'REVUPD','REVCOMM','APPCOMM','APP','REJCOMM','REJ','INTREJ','APPUN')
AND WOR_DATE_ATTRIB131 BETWEEN (select min(st_range) from Date_range) AND (select max(end_range) from Date_range)
)
, haud as (
select h.*, range_value from haud_a h, Date_range
where HAUD_TIMESTAMP BETWEEN st_range AND end_range
)
--
--
--
, claims as
(
select a.woc_works_order_no, a.woc_interim_no, woc_claim_value, claim_previous from
(select woc_works_order_no, woc_interim_no, woc_claim_value
, lag(woc_claim_value) over (partition by woc_works_order_no order by woc_interim_no Asc) as claim_previous
from work_order_claims
order by woc_works_order_no, woc_interim_no asc) a
, (select woc_works_order_no, max(woc_interim_no) woc_interim_no from work_order_claims group by woc_works_order_no) b
where a.woc_works_order_no = b.woc_works_order_no
and a. woc_interim_no = b.woc_interim_no
)
--
, main as (
SELECT DISTINCT
'<p title="Click for forms" id="'||works_order_number||'" onmouseover="showWOLDetails(this);">'|| WORKs_ORDER_NUMBER||'</p>' WORKS_ORDER_NUMBER
,decode( DECODE (mai_sdo_util.wo_has_shape (hig.get_sysopt ('SDOWOLNTH'), wor.works_order_number),
'TRUE', 'Y','N'),
'N',
'<img width=24 height=24 src="/im4_framework/images/grey_globe.png" title="No Location">'
,'') map
,decode(im_framework.has_doc(works_order_number,'WORK_ORDERS'),0,
'<img width=24 height=24 src="/im4_framework/images/mfclosed.gif" title="No Documents">'
,'') DOCS
,(select ial_meaning from nm_inv_attri_lookup where ial_domain = 'INVOICE_STATUS' and ial_value = wor_char_attrib110) INVOICE_STATUS
,WOR_CHAR_ATTRIB111 as "INVOICE_STATUS_COMMENT"
,works_order_description
, claim_previous Previous_Claim_Amount
, woc_claim_value New_Claim_Amount
, WOR_CHAR_ATTRIB111 Claim_Comments
,bud.work_category_description Budget_Description
, 'BOQ' BOQ
,WOR_CHAR_ATTRIB115 "Correct area of work "
,WOR_CHAR_ATTRIB116 "Quality of Work OK"
,WOR_CHAR_ATTRIB70 "Correct BOQ_Uplifts"
,WOR_CHAR_ATTRIB113 "Before_After_Photos_Present" --"Before After Photos Present"
,WOR_CHAR_ATTRIB114 "Certification Comments"
--,(select hus_name from hig_audits, hig_users where haud_pk_id = haud.haud_pk_id and haud_timestamp = haud.haud_timestamp and haud_new_value = haud.haud_new_value and haud_attribute_name = haud.haud_attribute_name and rownum =1) Reviewed_By
, (select HUS_NAME from hig_users where hus_user_id = WOR_NUM_ATTRIB04 ) Reviewed_By
, works_order_number wor_number
, 'Edit' rec_edit
--
FROM imf_mai_work_orders_all_attrib wor,
imf_mai_work_order_lines wol,
haud
,claims
,imf_mai_budgets bud
,pod_nm_element_security,
pod_budget_security
WHERE 1=1
and wol.budget_id = bud.budget_id
AND works_order_number = haud_pk_id
AND works_order_number = claims.woc_works_order_no(+)
AND works_order_number = work_order_number
AND pod_nm_element_security.element_id = wol.network_element_id
AND pod_budget_security.BUDGET_CODE = wol.work_category
AND WOR_CHAR_ATTRIB110 = haud_new_value
AND range_value = :P40_DAYS
AND WOR_CHAR_ATTRIB110 = :P40_PRIORITY
)
--
Select * from main;
Setting Context just uses DBMS_SESSION package as follows -
DBMS_SESSION.SET_CONTEXT('NM3SEC', p_attribute, p_value);
In this case - p_attribute is USERNAME
You can't use DBMS_SESSION with apex since it's a stateless framework pooling multiple connections between multiple sessions.
Apex uses url based session-id's.
You should rather
1) Create an application item in Shared Components.
2) Set the value of the item as a post login procedure using apex_util.set_session_state
Use the value of that item in your SQL code.

Suppress ORA-01403: no data found excpetion

I have the following code
SELECT SUM(nvl(book_value,
0))
INTO v_balance
FROM account_details
WHERE currency = 'UGX';
--Write the balance away
SELECT SUM(nvl(book_value,
0))
INTO v_balance
FROM account_details
WHERE currency = 'USD';
--Write the balance away
Now the problem is, there might not be data in the table for that specific currency, but there might be data for the 'USD' currency. So basically I want to select the sum into my variable and if there is no data I want my stored proc to continue and not throw the 01403 exception.
I don't want to put every select into statement in a BEGIN EXCEPTION END block either, so is there some way I can suppress the exception and just leave the v_balance variable in an undefined (NULL) state without the need for exception blocks?
select nvl(balance,0)
into v_balance
from
(
select sum(nvl(book_value,0)) as balance
from account_details
where currency = 'UGX'
);
SELECT L1.PKCODE L1CD, L1.NAME L1N, L1.LVL L1LVL,
L2.PKCODE L2CD, L2.NAME L2N, L2.LVL L2LVL,
L5.PKCODE L5CD, L5.NAME L5N,
INFOTBLM.OPBAL ( L5.PKCODE, :PSTDT, :PSTUC, :PENUC, :PSTVT, :PENVT ) OPBAL,
INFOTBLM.DEBIT ( L5.PKCODE, :PSTDT,:PENDT, :PSTUC, :PENUC, :PSTVT, :PENVT ) AMNTDR,
INFOTBLM.CREDIT ( L5.PKCODE, :PSTDT,:PENDT, :PSTUC, :PENUC, :PSTVT, :PENVT ) AMNTCR
FROM FSLVL L1, FSLVL L2, FSMAST L5
WHERE L2.FKCODE = L1.PKCODE
AND L5.FKCODE = L2.PKCODE
AND L5.PKCODE Between :PSTCD AND NVL(:PENCD,:PSTCD)
GROUP BY L1.PKCODE , L1.NAME , L1.LVL ,
L2.PKCODE , L2.NAME , L2.LVL ,
L5.PKCODE , L5.NAME
ORDER BY L1.PKCODE, L2.PKCODE, L5.PKCODE

Resources