Oracle SubQuery (Display subquery columns) - sql

I cannot seem to find via searching how I would be able to return some of the columns from the the below sub queries. Specifically B.TAP_STAT_HSL/C.TAP_STAT_HSL. I'm not sure if I should be joining instead, but any help would be greatly appreciated.
SELECT
A.HSE_KEY_HSE AS HOUSEKEY,
A.DROP_STAT_HSE AS DROPSTATUS
A.TAP_STAT_HSL AS ITAPSTAT
FROM OPS$SEA.HSE_BASE,OPS$SEA.HSL_LOB,OPS$SEA.OOR_ORDER_OPEN A
WHERE A.HSE_KEY_HSE = A.HSE_KEY_HSL
AND A.HSE_KEY_HSL = A.HSE_KEY_OOR
AND A.DROP_STAT_HSE = '1'
AND A.LOB_IND_HSL = 'I'
AND A.TAP_STAT_HSL IN ('0','2')
AND A.ORD_STAT_OOR <> 'O'
AND EXISTS (SELECT 1
FROM OPS$SEA.HSE_BASE B,OPS$SEA.HSL_LOB B, OPS$SEA.OOR_ORDER_OPEN B
WHERE A.HSE_KEY_HSE = B.HSE_KEY_HSE
AND B.HSE_KEY_HSE = B.HSE_KEY_HSL
AND B.HSE_KEY_HSL = B.HSE_KEY_OOR
AND B.DROP_STAT_HSE = '1'
AND B.LOB_IND_HSL = 'C'
AND B.TAP_STAT_HSL IN ('0','2')
AND B.ORD_STAT_OOR <> 'O')
AND EXISTS (
SELECT 1
FROM OPS$SEA.HSE_BASE C,OPS$SEA.HSL_LOB C, OPS$SEA.OOR_ORDER_OPEN C
WHERE A.HSE_KEY_HSE = C.HSE_KEY_HSE
AND C.HSE_KEY_HSE = C.HSE_KEY_HSL
AND C.HSE_KEY_HSL = C.HSE_KEY_OOR
AND C.DROP_STAT_HSE = '1'
AND C.LOB_IND_HSL = 'T'
AND C.TAP_STAT_HSL IN ('0','2')
AND C.ORD_STAT_OOR <> 'O')}

Hmmm....
I believe your query can be re-written as follows:
WITH Allowed_Rows (houseKey, dropStatus, ipApStat, indicator)
as (SELECT a.HSE_KEY_HSE, a.DROP_STAT_HSE,
b.TAP_STAT_HSL, b.LOB_IND_HSL
FROM OPS$SEA.HSE_BASE as a
JOIN OPS$SEA.HSL_LOB as b
ON b.HSE_KEY_HSL = a.HSE_KEY_HSE
AND b.LOB_IND_HSL IN ('I', 'C', 'T')
AND b.TAB_STAT_HSL IN ('0', '2')
JOIN OPS$SEA.OOR_Order_Open as c
ON c.HSE_KEY_OOR = a.HSE_KEY_HSE
AND c.ORD_STAT_OOR <> '0'
WHERE a.DROP_STAT_HSE = '1')
SELECT houseKey, dropStatus, ipApStat
FROM Allowed_Rows as a
WHERE a.indicator = 'I'
AND EXISTS (SELECT '1'
FROM Allowed_Rows as b
WHERE b.houseKey = a.houseKey
AND b.indicator = 'C')
AND EXISTS (SELECT '1'
FROM Allowed_Rows as b
WHERE b.houseKey = a.houseKey
AND b.indicator = 'T')
You didn't properly qualify some of your tables, and used the same alias for multiple tables (which I'm surprised didn't generate a syntax error), so I had to make my best guess as to where things actually belong. There are a couple of other variations possible, depending on the other (unlisted) requirements and constraints.
And why and how do you need to return the 'other' values of TAP_STAT_HSL? DO you need all possible combinations? The value of the row for B or C instead of A? What?

Related

Using a CASE WHEN statement and an IN (SELECT...FROM) subquery

I'm trying to create a temp table and build out different CASE WHEN logic for two different medications. In short I have two columns of interest for these CASE WHEN statements; procedure_code and ndc_code. There are only 3 procedure codes that I need, but there are about 20 different ndc codes. I created a temp.ndcdrug1 temp table with these ndc codes for medication1 and temp.ndcdrug2 for the ndc codes for medication2 instead of listing out each ndc code individually. My query looks like this:
CREATE TABLE temp.flags AS
SELECT DISTINCT a.userid,
CASE WHEN (procedure_code = 'J7170' OR ndc_code in (select ndc_code from temp.ndcdrug1)) THEN 'Y' ELSE 'N' END AS Drug1,
CASE WHEN (procedure_code = 'J7205' OR procedure_code = 'C9136' OR ndc_code in (select ndc_code from temp.ndcdrug2)) THEN 'Y' ELSE 'N' END AS Drug2,
CASE WHEN (procedure_code = 'J7170' AND procedure_code = 'J7205') THEN 'Y' ELSE 'N' END AS Both
FROM table1 a
LEFT JOIN table2 b
ON a.userid = b.userid
WHERE...
AND...
When I run this, it returns: org.apache.spark.sql.AnalysisException: IN/EXISTS predicate sub-queries can only be used in a Filter.
I could list these ndc_code values out individually, but there are a lot of them so wanted a more efficient way of going about this. Is there a way to use a sub select query like this when writing out CASE WHEN's?
Query.
CREATE TABLE temp.flags AS
SELECT DISTINCT a.userid,
CASE WHEN (
procedure_code = 'J7170' OR
(select min('1') from temp.ndcdrug1 m where m.ndc_code = a.ndc_code) = '1'
) THEN 'Y' ELSE 'N' END AS Drug1,
CASE WHEN (
procedure_code = 'J7205' OR
procedure_code = 'C9136' OR
(select min('1') from temp.ndcdrug2 m where m.ndc_code = a.ndc_code) = '1'
) THEN 'Y' ELSE 'N' END AS Drug2,
CASE WHEN (procedure_code = 'J7170' AND procedure_code = 'J7205')
THEN 'Y' ELSE 'N' END AS Both
FROM table1 a
LEFT JOIN table2 b
ON a.userid = b.userid
WHERE...
AND...

Optimizing query with multiple CASEs with Count depending on column content

I have a part of a query which I am trying to optimize. My tables have a lot of info and it would be good for us to know if we could optimize it a little bit.
This part is the one that is taking longer:
CASE
WHEN {SPS_FACTURAS}.[TipoFactura] = 'F'
AND {SPS_FACTURAS}.[IsPurged] = 0 THEN (SELECT COUNT(DISTINCT NumRec)
FROM {SPS_LINFARMA} linfarma
WHERE linfarma.[IdCodFact] = {SPS_FACTURAS}.[IdCodFact])
WHEN {SPS_FACTURAS}.[TipoFactura] = 'F'
AND {SPS_FACTURAS}.[IsPurged] = 1 THEN (SELECT COUNT(DISTINCT NumRec)
FROM {SPS_HISTLINFARMA} histfarm
WHERE histfarm.[IdCodFact] = {SPS_FACTURAS}.[IdCodFact])
WHEN {SPS_FACTURAS}.[TipoFactura] = 'C'
AND {SPS_FACTURAS}.[NomUsrIns] <> 'WS_Faturacao'
AND {SPS_FACTURAS}.[IsPurged] = 0 THEN (SELECT COUNT(DISTINCT NUMFICH)
FROM {SPS_LINFACT2} linha
WHERE linha.[IdCodFact] = {SPS_FACTURAS}.[IdCodFact])
WHEN {SPS_FACTURAS}.[TipoFactura] = 'C'
AND {SPS_FACTURAS}.[NomUsrIns] <> 'WS_Faturacao'
AND {SPS_FACTURAS}.[IsPurged] = 1 THEN (SELECT COUNT(DISTINCT NUMFICH)
FROM {SPS_HISTLINFACT} histlin
WHERE histlin.[IdCodFact] = {SPS_FACTURAS}.[IdCodFact])
WHEN {SPS_FACTURAS}.[TipoFactura] = 'C'
AND {SPS_FACTURAS}.[NomUsrIns] = 'WS_Faturacao'
THEN (SELECT COUNT(DISTINCT NUMFICH)
FROM {SPS_LINFACTWS} linWS
WHERE linWS.[IdCodFact] = {SPS_FACTURAS}.[IdCodFact])
END
Is there a way I can optimize it?
Thanks a lot in advance,
Vincent Colpa

How to tune this query in Oracle 11g

I have been asked to tune the below query and would like to know if there is any better way to tune it?
SELECT req_dtl.lab_ord_occ_test_id ,
req_dtl.order_ref_no ,
req_dtl.accession_no ,
req_dtl.test_code ,
req_dtl.test_name ,
req_dtl.test_id ,
req_dtl.schedule_id ,
req_dtl.lab_ord_occ_id ,
req_dtl.order_type ,
lab_occ.facility_id ,
lab_occ.patient_id ,
lab_occ.order_draw_dt ,
hdr.source_system ,
(SELECT CORPORATION_ACRONYM
FROM corporation c,
facility f
WHERE c.corporation_id = f.corporation_id
AND f.facility_id = lab_occ.facility_id) AS corporation_acronym,
tst.container ,
lab_occ.order_duration_type ,
occ_test.mnc_yn
FROM ORDER_REQUISITION_HEADER hdr ,
ORDER_REQUISITION_DETAIL req_dtl ,
LAB_ORDER_OCC_TEST occ_test ,
LAB_ORDER_OCC lab_occ ,
TEST tst
WHERE hdr.requisition_hdr_id = in_requisition_hdr_id
AND hdr.msg_sent_to_lab_yn = 'Y'
AND req_dtl.requisition_hdr_id = hdr.requisition_hdr_id
AND occ_test.lab_order_occ_test_id = req_dtl.lab_ord_occ_test_id
AND req_dtl.test_id = tst.test_id
AND tst.accession_type NOT LIKE 'CMP%'
AND occ_test.status != 'R'
AND occ_test.lab_order_occ_id = lab_occ.lab_order_occ_id
AND lab_occ.status = 'A'
AND occ_test.created_dt >= hdr.msg_sent_to_lab_dt
AND NVL(occ_test.test_sent_to_lab_yn,'N') = 'N'
AND NOT EXISTS
(SELECT orddata.*
FROM MISSING_ORDER_DATA orddata,
TEST_CONFIG_HOLD_AOE tcha
WHERE orddata.test_id = tcha.test_id
AND tcha.active_yn = 'Y'
AND orddata.status_flag = 'A'
AND orddata.answer IS NULL
AND orddata.msg_sent_to_lab_yn = 'N'
AND orddata.lab_order_occ_test_id=occ_test.lab_order_occ_test_id
)
ORDER BY req_dtl.accession_no;
In the execution plan no tables are going for full table scan.Only nested loops are more.
*Suggest better way to tune this query *
AND NOT EXISTS
(SELECT orddata.*
FROM MISSING_ORDER_DATA orddata,
TEST_CONFIG_HOLD_AOE tcha
WHERE orddata.test_id = tcha.test_id
AND tcha.active_yn = 'Y'
AND orddata.status_flag = 'A'
AND orddata.answer IS NULL
AND orddata.msg_sent_to_lab_yn = 'N'
AND orddata.lab_order_occ_test_id=occ_test.lab_order_occ_test_id
)
could be moved to FROM
FROM
...
LEFT JOIN (SELECT DISTINCT orddata.lab_order_occ_test_id
FROM MISSING_ORDER_DATA orddata,
TEST_CONFIG_HOLD_AOE tcha
WHERE orddata.test_id = tcha.test_id
AND tcha.active_yn = 'Y'
AND orddata.status_flag = 'A'
AND orddata.answer IS NULL
AND orddata.msg_sent_to_lab_yn = 'N'
) missing ON missing.lab_order_occ_test_id = occ_test.lab_order_occ_test_id
WHERE missing.lab_order_occ_test_id IS NULL
Also you should move the acronym
FROM
...
INNER JOIN (SELECT CORPORATION_ACRONYM, f.facility_id
FROM corporation c,
facility f
WHERE c.corporation_id = f.corporation_id) acr ON
acr.facility_id = lab_occ.facility_id)
...Additionally, the TEST object must have an index on accession_type otherwise the tst.accession_type not like 'CMP%' clause will be slower than necessary.
Also, the clause: NVL(occ_test.test_sent_to_lab_yn,'N') = 'N' is essentially an outer join on partially-validated data. Does the test_sent_to_lab_yn column in occ_test contain nulls? If not, consider using an IN clause along with a valid list. [it looks like a yes/no column, maybe this should be equality on 'Y' and get someone to clean up the nulls?]
Please post the explain plan so we can suggest a re-ordering of the predicates in order to minimize the row-returns in first clause....and make HINT suggestions.

How to do inner join in Vertica Update?

I was trying to do a inner join with 3 tables in a update query. I tried to find the solution in multiple sites but didn't get the solution.
Following a sample query I am trying:
UPDATE TGT
SET C1 = CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'P' THEN SRC.C1 ELSE NULL END,
C2 = CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'D' THEN SRC.C1 ELSE NULL END
FROM SRC
INNER JOIN SRC1
ON SRC.C9 = SRC1.C9
AND SRC.C9 = TGT.C9;
Thanks in Advance!!
I would expect your syntax to work. (I don't have Vertica handy but its query parser is based on Postgres.)
Perhaps -- unlike Postgres -- JOIN is not allowed in the FROM. Then you can put the join conditions in the WHERE clause:
UPDATE TGT
SET C1 = (CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'P' THEN SRC.C1 END)
C2 = (CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'D' THEN SRC.C1 END)
FROM SRC, SRC1
WHERE SRC.C9 = SRC1.C9 AND SRC.C9 = TGT.C9;

Merge Source Table Into Target Table using subjoins

I am new to SQLDeveloper. Please help me in correcting the merge syntax.I want to merge the data from act_sl tavle into act_sls_0 table
I am using 2 joins in From Clause.
But I am Getting Errors :
Error(13,13): PL/SQL: ORA-00969: missing ON keyword
Error(4,1): PL/SQL: SQL Statement ignored
merge into act_sls_0 using(
( select * from
(select a_0.asp, gadim.uic as ga, pmm_styleid, week, colorcode , sizecode, storenum, units_asly,retail_asly,
cost_asly ,units_asregly,retail_asregly,units_asmkdly,retail_asmkdly,units_as_pln,retail_as_pln
from act_sls
join dimension w on w.externalkey = 'W'||substr(WEEK,3,2)||'_'||substr(WEEK,5,2)
join a_0 on ( w.externalkey between startweek and endweek)
join dimension strdim on strdim.externalkey = (case when length(storenum) <= 4 then RPAD('STR-', 8 - length(storenum), '0') else 'STR-' END) || storenum
join store_info_0 str on store = strdim.uic
join dimension gadim on gadim.externalkey = decode(store_type, 'RETAIL', 'GA-01', 'ECOM', 'GA-02', '')
where trendweeks < 6)t1
join(select distinct asp, product, ga, color, sstyl_shade, pmm_styleid from aplc_1 aplc
join apc_1 apc using (asp,product,color)
where activeitem = 1 and ga!=0 and color != 0)t2
on (t1.asp = t2.asp and
t1.pmm_styleid = t2.pmm_styleid
and (case when length(t1.colorcode) <= 4 then RPAD('SHD-', 8 - length(t1.colorcode), '0') else 'SHD-' END) || t1.colorcode = t2.sstyl_shade
and t1.ga = t2.ga))src
on (trg.asp = src.asp and trg.pmm_styleid = src.pmm_styleid and trg.colorcode = src.colorcode and trg.ga = src.ga)
when matched THEN
update SET
when matched THEN
update SET
trg.UNITS_ASLY = src.UNITS_ASLY,
trg.RETAIL_ASLY = src.RETAIL_ASLY,
trg.COST_ASLY = src.COST_ASLY,
trg.UNITS_ASREGLY = src.UNITS_ASREGLY,
trg.RETAIL_ASREGLY = src.RETAIL_ASREGLY,
trg.UNITS_ASMKDLY = src.UNITS_ASMKDLY,
trg.RETAIL_ASMKDLY = src.RETAIL_ASMKDLY,
trg.UNITS_AS_PLN = src.UNITS_AS_PLN,
trg.RETAIL_AS_PLN = src.RETAIL_AS_PLN
when not matched then insert
(trg.asp,trg.ga, trg.pmm_styleid, trg.colorcode,trg.sizecode,trg.storenum,trg.week,trg.UNITS_ASLY,trg.RETAIL_ASLY ,trg.COST_ASLY , trg.UNITS_ASREGLY ,trg.RETAIL_ASREGLY ,
trg.UNITS_ASMKDLY ,trg.RETAIL_ASMKDLY ,trg.UNITS_AS_PLN ,trg.RETAIL_AS_PLN )
values
(src.asp,src.ga, src.pmm_styleid, src.colorcode,src.sizecode,src.storenum,src.week,src.UNITS_ASLY,src.RETAIL_ASLY,src.COST_ASLY,src.UNITS_ASREGLY,
src.RETAIL_ASREGLY, src.UNITS_ASMKDLY, src.RETAIL_ASMKDLY, src.UNITS_AS_PLN, src.RETAIL_AS_PLN);
The format for a merge statement is:
merge into <target_table> tgt
using <table_name or subquery> src
on (<join conditions between the target and source datasets>)
when matched then
update set ...
when not matched then
insert (...)
values (...);
Quite apart from the fact that your source subquery is incorrect (there are errors around where the t1 and t2 are; too many brackets, inappropriately trying to alias something etc), whilst you have join conditions inside your subquery, you're completely missing the ON clause for the merge itself.
You need to define the join conditions that match the data returned by your source subquery to your target table.
Now the error is : src.ga - Invalid Identifier
Although I have ga table in Trg table and src table .
merge into act_sls_0 trg using( select * from
(select a_0.asp, gadim.uic as ga, pmm_styleid, week, colorcode , sizecode, storenum, units_asly,retail_asly,
cost_asly ,units_asregly,retail_asregly,units_asmkdly,retail_asmkdly,units_as_pln,retail_as_pln
from act_sls
join dimension w on w.externalkey = 'W'||substr(WEEK,3,2)||'_'||substr(WEEK,5,2)
join a_0 on ( w.externalkey between startweek and endweek)
join dimension strdim on strdim.externalkey = (case when length(storenum) <= 4 then RPAD('STR-', 8 - length(storenum), '0') else 'STR-' END) || storenum
join store_info_0 str on store = strdim.uic
join dimension gadim on gadim.externalkey = decode(store_type, 'RETAIL', 'GA-01', 'ECOM', 'GA-02', '')
where trendweeks < 6)t1
join(select distinct asp, product, ga, color, sstyl_shade, pmm_styleid from aplc_1 aplc
join apc_1 apc using (asp,product,color)
where activeitem = 1 and ga!=0 and color != 0)t2
on (t1.asp = t2.asp and
t1.pmm_styleid = t2.pmm_styleid
and (case when length(t1.colorcode) <= 4 then RPAD('SHD-', 8 - length(t1.colorcode), '0') else 'SHD-' END) || t1.colorcode = t2.sstyl_shade
and t1.ga = t2.ga))src
on (trg.asp = src.asp and trg.pmm_styleid = src.pmm_styleid and trg.colorcode = src.colorcode and trg.ga = src.ga)
when matched THEN
update SET
trg.UNITS_ASLY = src.UNITS_ASLY,
trg.RETAIL_ASLY = src.RETAIL_ASLY,
trg.COST_ASLY = src.COST_ASLY,
trg.UNITS_ASREGLY = src.UNITS_ASREGLY,
trg.RETAIL_ASREGLY = src.RETAIL_ASREGLY,
trg.UNITS_ASMKDLY = src.UNITS_ASMKDLY,
trg.RETAIL_ASMKDLY = src.RETAIL_ASMKDLY,
trg.UNITS_AS_PLN = src.UNITS_AS_PLN,
trg.RETAIL_AS_PLN = src.RETAIL_AS_PLN
when not matched then insert
(trg.asp,trg.ga, trg.pmm_styleid, trg.colorcode,trg.sizecode,trg.storenum,trg.week,trg.UNITS_ASLY,trg.RETAIL_ASLY ,trg.COST_ASLY ,trg.UNITS_ASREGLY ,trg.RETAIL_ASREGLY ,
trg.UNITS_ASMKDLY ,trg.RETAIL_ASMKDLY ,trg.UNITS_AS_PLN ,trg.RETAIL_AS_PLN )
values
(src.asp,src.ga, src.pmm_styleid, src.colorcode,src.sizecode,src.storenum,src.week,src.UNITS_ASLY,src.RETAIL_ASLY,src.COST_ASLY,src.UNITS_ASREGLY,
src.RETAIL_ASREGLY, src.UNITS_ASMKDLY, src.RETAIL_ASMKDLY, src.UNITS_AS_PLN, src.RETAIL_AS_PLN);
commit;