Put database field in the RHS on the WHERE condition? - abap

How we can write the below WHERE?
SELECT * FROM acdoca
WHERE koart = #(COND #( blart = 'DY' THEN 'D' ELSE 'S' ) )
It does not recognize the field name BLART. How can we pass it?
Thanks
Elias
EDIT: here is the whole WHERE:
WHERE acdoca~rldnr = '0L' AND
acdoca~rbukrs = #company_code AND
acdoca~belnr IN #document_no_range AND
acdoca~gjahr = #year AND
acdoca~koart = #(COND #( blart = 'DY' THEN 'D' ELSE 'S' ) )

​A Host Expression #( ... ) is only interpreted at ABAP side, there is absolutely no interaction with the database server, the expression is evaluated and the SQL statement is updated with the result before it is sent to the database.
If I understand well what you want to achieve, this should work:
SELECT * FROM acdoca
WHERE ( blart = 'DY' and koart = 'D' )
OR ( blart <> 'DY' and koart = 'S' )
INTO TABLE #DATA(itab).
NB: if I didn't understand well and you really want a Host Expression, a valid syntax would be this one:
DATA blart TYPE acdoca-blart.
SELECT * FROM acdoca
WHERE koart = #( COND #( WHEN blart = 'DY' THEN 'D' ELSE 'S' ) )
INTO TABLE #DATA(itab).
EDIT: here is the complement to the EDIT of the question, the whole correct WHERE would be:
WHERE acdoca~rldnr = '0L' AND
acdoca~rbukrs = #company_code AND
acdoca~belnr IN #document_no_range AND
acdoca~gjahr = #year AND
( ( acdoca~blart <> 'DY' AND acdoca~koart = 'S' ) OR
( acdoca~blart = 'DY' AND acdoca~koart = 'D' ) )

Related

merge CTE query in Oracle

I am looking for an optimized way to merge CTE query as mentioned below. In the below query, the same table is getting hit twice, I am looking for an option to hit this table once and it will only be possible if I remove CTE and put everything into single query. I am using CTE as I need to derive column value and then compare that value..
Query
with cte as
(
select distinct
'UP' search_update_code,
'G' search_prov_entity_type,
prpr.prpr_id search_prov_id,
prpr.mctn_id search_tax_id,
'UP' group_provdata_upd_cd,
'G' group_provdata_entity,
case
when enroll_type = 'AH' THEN 'A'
when enroll_type = 'VP' THEN 'A'
when enroll_type = 'CK' THEN ' '
end group_provdata_clm_eft_pay_ind <-- deriving values here
from
fsg_prcb_pe_enroll_stream prcb
inner join
cmc_prpr_prov prpr on prpr.mctn_id = prcb.prov_tin_number <-- 1st hit
where
prpr.prpr_entity ='G'
and prcb.prov_tin_number = ?
and prcb.error_flag is null
)
select distinct
cte.*
from cte
inner join cmc_prpr_prov prpr on cte.search_prov_id = prpr.prpr_id <-- 2nd hit
where cte.group_provdata_clm_eft_pay_ind <> prpr.prpr_cl_eft_ind <--- comparing derived values here
and prpr_term_dt >= systimestamp
You can rewrite your query like below:
with cte as
(
select distinct
'UP' search_update_code,
'G' search_prov_entity_type,
prpr.prpr_id search_prov_id,
prpr.mctn_id search_tax_id,
'UP' group_provdata_upd_cd,
'G' group_provdata_entity,
case
when enroll_type = 'AH' THEN 'A'
when enroll_type = 'VP' THEN 'A'
when enroll_type = 'CK' THEN ' '
end group_provdata_clm_eft_pay_ind, <-- deriving values here
prpr.prpr_cl_eft_ind prpr_cl_eft_ind_2,
prpr_term_dt
from
fsg_prcb_pe_enroll_stream prcb
inner join
cmc_prpr_prov prpr on prpr.mctn_id = prcb.prov_tin_number <-- 1st hit
where
prpr.prpr_entity ='G'
and prcb.prov_tin_number = ?
and prcb.error_flag is null
)
select distinct
cte.*
from cte
where group_provdata_clm_eft_pay_ind <> prpr_cl_eft_ind_2 <--- comparing derived values here
and prpr_term_dt >= systimestamp

Possible way to increase joins performance to SQL query for Oracle database

I am having a query whose performance is really bad, like it takes more than 15 min. to get 6000 rows worth of data. I'm not sure if this is caused by my joins or bad query or my schema.
Can someone please help me, it would be very super helpful to know if there is a performance issue. What are the best steps to follow? Which part of my query is causing poor performance?
WITH ship AS (
SELECT
"ORDER"
FROM
historymaster hm
WHERE
--datetimecreated BETWEEN TO_char(:startdate,'MM-DD-YYYY') AND
TO_char(:enddate +1 ,'MM-DD-YYYY')
datetimecreated BETWEEN TO_DATE(:startdate,'MM-DD-YYYY') AND
TO_DATE(:enddate,'MM-DD-YYYY')
AND "OBJECT" = 'OBORDLINE'
AND hm.package = ' '
AND actionmodifier IS NULL
AND "ACTION" = 'SHIP'
),cpt_time AS (
SELECT
unique(outboundorder),
TO_CHAR(shipdatetime,'yyyy-mm-dd hh24:mi') AS cpt,
routingcomments1,
routingcomments2
FROM
history_outbound_order_master
WHERE
outboundorder IN (
SELECT
"ORDER"
FROM
ship
)
AND routingcomments2 IS NOT NULL
),transations AS (
SELECT
"ORDER",
datetimecreated,
datecreated,
TO_CHAR(datetimecreated,'yyyy-mm-dd hh24:mi') AS ship_complete_time,
actualquantity,
"ACTION",
warehouse AS site
FROM
historymaster hm
WHERE
--datetimecreated BETWEEN TO_DATE(:startdate,'MM-DD-YYYY') AND
TO_DATE(:enddate,'MM-DD-YYYY')
-- ship complete
"ORDER" IN (
SELECT
"ORDER"
FROM
ship
)
AND (
(
"OBJECT" = 'OBORDLINE'
AND hm.package = ' '
AND actionmodifier IS NULL
AND "ACTION" = 'SHIP'
)
OR -- pick
(
"ACTION" = 'PICK'
AND "OBJECT" = 'OBO'
AND "CLASS" = 'INVE'
AND actualquantity != 0
AND substr(ordertype,1,1) = 'N'
)
OR -- Order drop
(
"ACTION" = 'DNLD'
AND "OBJECT" = 'OBORDLINE'
AND actionmodifier IS NULL
AND reasoncode = '00'
)
OR --label request
(
"ACTION" = 'REQUEST'
AND "OBJECT" = 'LABEL'
AND "CLASS" = 'ADDR'
)
OR (
"ACTION" = 'LOAD'
AND "OBJECT" = 'OBO'
AND "CLASS" = 'INVE'
)
)
) SELECT
"ORDER",
MAX(
CASE
WHEN "ACTION" = 'DNLD' THEN ship_complete_time
END
) AS order_drop_time,
MAX(
CASE
WHEN "ACTION" = 'REQUEST' THEN ship_complete_time
END
) AS label_request_time,
MAX(
CASE
WHEN "ACTION" = 'PICK' THEN ship_complete_time
END
) AS pick_time,
MAX(
CASE
WHEN "ACTION" = 'LOAD' THEN ship_complete_time
END
) AS load_time,
MAX(
CASE
WHEN "ACTION" = 'SHIP' THEN ship_complete_time
END
) AS ship_com_time,
cpt,
routingcomments1,
routingcomments2
FROM
transations left
JOIN cpt_time ON "ORDER" = outboundorder
GROUP BY
"ORDER",
routingcomments1,
routingcomments2,
cpt
If the values of the column are not uniform distributed, ensure column statistics are gathered.
If every sub-select for itself runs fast, add the hint /*+ materialize */ to the selects to ensure it runs as planned.

Need help on how to convert this select to a DELETE statement:

I need help as to how to convert this select to a delete statement.
SELECT stud_term_sum_div.id_num,
stud_term_sum_div.hrs_enrolled,
stud_term_sum_div.transaction_sts,
student_crs_hist.crs_cde,
student_crs_hist.transaction_sts
FROM stud_term_sum_div,
student_crs_hist
WHERE ( stud_term_sum_div.yr_cde = student_crs_hist.yr_cde ) and
( stud_term_sum_div.trm_cde = student_crs_hist.trm_cde ) and
( stud_term_sum_div.id_num = student_crs_hist.id_num ) and
( ( stud_term_sum_div.yr_cde = '2013' ) AND
( stud_term_sum_div.trm_cde = 'FA' ) AND
( stud_term_sum_div.hrs_enrolled >= 3.00 ) AND
( student_crs_hist.transaction_sts = 'D' ) )
The most straight-forward conversion is below:
DELETE * FROM stud_term_sum_div
WHERE ( stud_term_sum_div.yr_cde = student_crs_hist.yr_cde ) and
( stud_term_sum_div.trm_cde = student_crs_hist.trm_cde ) and
( stud_term_sum_div.id_num = student_crs_hist.id_num ) and
( ( stud_term_sum_div.yr_cde = '2013' ) AND
( stud_term_sum_div.trm_cde = 'FA' ) AND
( stud_term_sum_div.hrs_enrolled >= 3.00 ) AND
( student_crs_hist.transaction_sts = 'D' ) )
BUT, before you go executing that, please check that the WHERE clause really contains the conditions to be used for deletion. Note that this SQL statement will delete the entire row (a/k/a record) when the attributes in the WHERE clause satisfy the stated conditions.
If you only want to remove the data from the attributes (as opposed to the entire record), you'd need to use an SQL UPDATE statement instead. The (simplified) syntax for that is as follows:
UPDATE <table_name>
SET <attribute1> = <value1>
[, SET <attribute_n> = <value_n>...]
WHERE <conditions on which the record should be updated>
Doing a search on Bing, google, <insert your favorite search engine here> for "SQL DELETE" or "SQL UPDATE" should get you all the information you need (e.g. MSDN, for one).

SQL - Return fields ONLY containing met requirement

I am trying to do the following:
Assign a Y/N flag as Prior Approval which includes all policies that are policies with BI limit 25/50 and PD limit 25 and no other coverage.
So this code satisfies the first requirements:
SELECT DISTINCT
PolNum
FROM Results_Vehicle
WHERE ( CovCode = 'BI'
AND CovLimit = '25/50'
)
OR ( CovCode = 'PD'
AND CovLimit = '25'
)
I can't figure out how to not include records that have other coverage. So basically for each policy they can have CovCodes of UMBI, COL, REN, BI, PD, etc. But the flag should only give a Y if for that PolNum they ONLY have BI or PD as CovCode and the CovLimit defined above.
So also I'll need to put it in the Y/N format as follows, obviously this only satisfies the first part of the requirement:
SELECT CASE WHEN ( CovCode = 'BI'
AND CovLimit = '25/50'
)
OR ( CovCode = 'PD'
AND CovLimit = '25'
) THEN 'Y'
ELSE 'N'
END AS PriorApproval
FROM Results_Vehicle
How about this query below. The union query gives you a combined list of all the PolNum's that have that type of coverage, so then you do a not in to give you all the policy numbers that AREN'T in that list, and then you do a not in on that list, which should leave you with the PolNum's that only have the desired coverage and no other coverage.
SELECT CASE WHEN
(
(CovCode = 'BI' AND CovLimit = '25/50')
OR
(CovCode = 'PD' AND CovLimit = '25')
and PolNum not in
(
select PolNum from Results_Vehicle as r1 where PolNum not in
(
select PolNum from Results_Vehicle as r2
where CovCode = 'BI' and CovLimit = '25/50'
union
select PolNum from Results_Vehicle as r3
where CovCode = 'PD' AND CovLimit = '25'
)
)
) THEN 'Y'
ELSE 'N'
END AS PriorApproval
FROM Results_Vehicle

SQL Query takes to long to return data

Looking for a better way to write this query and my SQL skills aren't great, basic really so looking for any pointers to make this better. This is only the first two columns and the full report will have a further 10.
I'm taking a specific set of repair types and doing analysis on them with counts and calculations. The 1st is jobs brought forward to the current financial year and the second is total amount of jobs currently received.
SELECT
"Type",
(
SELECT
NVL (COUNT(jjo.jjobno), 0)
FROM
jjobh jjo
WHERE
jjo.jclcode = 'L'
AND jjo.jstatus <> '6'
AND jjo.year_rec <> (
SELECT
sub_code
FROM
code_table
WHERE
main_code = 'YEAR'
)
AND (
week_comp IS NULL
OR year_comp = (
SELECT
sub_code
FROM
code_table
WHERE
main_code = 'YEAR'
)
)
AND jjo.jrepair_type = "Type"
) AS "B/F",
(
SELECT
NVL (COUNT(jjo.jjobno), 0)
FROM
jjobh jjo
WHERE
jjo.jclcode = 'L'
AND jjo.jstatus <> '6'
AND jjo.year_rec = (
SELECT
sub_code
FROM
code_table
WHERE
main_code = 'YEAR'
)
AND jjo.jrepair_type = "Type"
) AS "Recvd"
FROM
(
SELECT
rep.repair_type_code AS "Type"
FROM
repair_type rep
WHERE
rep.client = 'L'
AND rep.work_centre = '004682'
ORDER BY
rep.repair_type_code
)
ORDER BY
"Type";
Your code is a mess. I suspect you want something like:
SELECT jjo.jrepair_type, count(*) as valbf
FROM (SELECT coalesce(COUNT(jjo.jjobno), 0)
FROM jjobh jjo cross join
(SELECT sub_code
FROM code_table
WHERE main_code = 'YEAR'
) sc
WHERE jjo.jclcode = 'L' AND
jjo.jstatus <> '6' AND
jjo.year_rec <> sc.sub_code AND
(week_comp IS NULL OR
year_comp = sc.sub_code
)
) jjo join
(SELECT rep.repair_type_code AS "Type"
FROM repair_type rep
WHERE rep.client = 'L' AND
rep.work_centre = '004682'
) rtc
on jjo.jrepair_type = rtc.repair_type_code
group by jjo.jrepair_type;
It looks like you want to join the "jjo" table to the "repair type code" table, producing information about each repair type. The order by in the subquery is useless.
My suggestion is to move the "jjo" table to the outer "from". You should also move the WHERE clauses to the outermost WHERE clause (which I didn't do). I haven't quite figured out the date logic, but this might get you on the right track.