SQL Query changing based on parameters - sql

a true IF...THEN statement would be useful here, but I am not aware of one. I have the user passing in 2 parameters (cfk_in and senr_in) into my query, and based on whether the param is Y or N, I will change my query, here is my current query:
select a.course_id, a.topic_code
from course_sections a,
statuses b
where a.course_id = b.course_id
and term = upper('2010FALL')
and status = 'P' and pos = 1
So this is pretty simple and would give me all sections and topic codes for a particular term. If the user passes in both params as 'N', I would like to just keep it at the above query. If the user passes in cfk_in = 'Y' and senr_in = 'N' then I would like to add "and a.topic_code = 'CFK%'", and like wise if the user passes in cfk_in = 'N' and senr_in = 'Y', I would like to add "and a.topic_code = 'SENR'". I am not allowing them to pass both in as 'Y'.
Is there a way to do this in one query? Thanks for the help.

It's quite simple:
[your query...]
and ((cfk_in = 'N' and senr_in = 'N') or
(cfk_in = 'Y' and senr_in = 'N' and a.topic_code like 'CFK%') or
(cfk_in = 'N' and senr_in = 'Y' and a.topic_code = 'SENR'))
This will also disallow passing both parameters as 'Y', as that would return no results. If cfk_in and senr_in aren't actual fields in your table, then mark them as bind variables:
[your query...]
and ((:cfk_in = 'N' and :senr_in = 'N') or
(:cfk_in = 'Y' and :senr_in = 'N' and a.topic_code like 'CFK%') or
(:cfk_in = 'N' and :senr_in = 'Y' and a.topic_code = 'SENR'))
Or with Java:
[your query...]
and ((? = 'N' and ? = 'N') or
(? = 'Y' and ? = 'N' and a.topic_code like 'CFK%') or
(? = 'N' and ? = 'Y' and a.topic_code = 'SENR'))
... binding cfk_in at indexes 1, 3, 5, and senr_in at indexes 2, 4, 6
N.B: I think you meant to filter a.topic_code like 'CFK%', not a.topic_code = 'CFK%'

Is there a way to do this in one query?
Absolutely. You can use OR to "mask out" parts of your query. For example,
AND (senr_in <> 'N' OR a.topic_code = 'CFK%')
will pay attention to topic_code only when senr_in = 'N'. Otherwise, the whole subexpression would evaluate to true, effectively excluding itself from the query condition.

Sure, there is a way. You could use your parameters in your where condition, like so:
select a.course_id, a.topic_code
from course_sections a,
statuses b
where a.course_id = b.course_id
and term = upper('2010FALL')
and status = 'P' and pos = 1
and ((cfk_in = 'Y' and senr_in = 'N' and a.topic_code like 'CFK%') or
(cfk_in = 'N' and senr_in = 'Y' and a.topic_code = 'SENR') or
(cfk_in = 'N' and senr_in = 'N'))

Yes, you can do this in one query.
Simpy add the following to your where clause:
(Note, I altered your a.topic_code = 'CFK%' to a.topic_code LIKE 'CFK%')
AND (#cfk_in = 'N' OR (#cfk_in = 'Y' AND a.topic_code LIKE 'CFK%'))
AND (#senr_in = 'N' OR (#senr_in = 'Y' AND a.topic_code = 'SENR'))

Related

How to improve SQL query when conditions grows dynamically

Usecase:
User want to get Sum amount by grouping a certain number of column values. To restrict the number of rows the Where condition is provided with the columns with their respective values.
Query Description:
Below is the SQL query in which the columns are decided dynamically as per the user requirement and at the same time the Groupby columns are also decided by the user dynamically.
In the Where condition, the condition grows dynamically depending upon the user selection.
SQL Query
SELECT transactionLine.department,
transactionLine.class,
transactionLine.cseg1,
transactionLine.cseg_grant,
transactionLine.cseg_restriction,
transactionLine.cseg_revtype,
transactionLine.cseg_rev_sub,
transactionLine.cseg_timerestrict,
transactionLine.cseg_fun_exp,
transactionLine.cseg_region,
BUILTIN_RESULT.TYPE_FLOAT(SUM(((NVL(CASE
WHEN transaction.posting = 'T' THEN TO_NUMBER(transactionaccountingLine.amount)
END, 0) + NVL(CASE
WHEN transaction.recordType = 'purchaseorder' THEN TO_NUMBER(transactionaccountingLine.amount)
END, 0)) - NVL(CASE
WHEN ((transaction.recordType = 'vendorbill'
AND BUILTIN.DF(transactionLine.createdfrom) IS NOT NULL)
AND UPPER(BUILTIN.DF(transaction_0.status)) NOT LIKE '%CLOSED%')
AND UPPER(BUILTIN.DF(transaction_0.status)) NOT LIKE '%FULLY BILLED%' THEN TO_NUMBER(transactionaccountingLine.amount)
END, 0)) + NVL(CASE
WHEN (transaction.recordType = 'vendorbill'
AND transaction.posting = 'F')
AND BUILTIN.DF(transactionLine.createdfrom) IS NOT NULL THEN TO_NUMBER(transactionaccountingLine.amount)
END, 0))) AS SUMNVLCASEWHENposting
FROM TRANSACTION,
account,
transactionaccountingLine,
TRANSACTION transaction_0,
transactionLine
WHERE ((((transactionaccountingLine.account = account.id(+)
AND (transactionLine.transaction = transactionaccountingLine.transaction
AND transactionLine.id = transactionaccountingLine.transactionline))
AND transactionLine.createdfrom = transaction_0.id(+))
AND transaction.id = transactionLine.transaction))
AND ((transactionLine.department= '11'
AND transactionLine.cseg_grant ='1'
AND transactionLine.class = '12'
AND transactionLine.cseg_restriction = '1'
AND transactionLine.cseg_revtype = '1'
AND transactionLine.cseg1 = '4'
AND transactionLine.cseg_rev_sub = '1'
AND transactionLine.cseg_timerestrict = '1'
AND transactionLine.cseg_fun_exp = '4'
AND transactionLine.cseg_region = '1') OR (transactionLine.department= '12'
AND transactionLine.cseg_grant ='1'
AND transactionLine.class = '12'
AND transactionLine.cseg_restriction = '1'
AND transactionLine.cseg_revtype = '1'
AND transactionLine.cseg1 = '4'
AND transactionLine.cseg_rev_sub = '1'
AND transactionLine.cseg_timerestrict = '1'
AND transactionLine.cseg_fun_exp = '4'
AND transactionLine.cseg_region = '1'))
AND ((NVL(account.custrecord_bm_budgetaccount, 'F') = 'F'
AND (NOT(UPPER(transaction.status) IN ('PURCHORD:H', 'PURCHORD:G', 'PURCHORD:A', 'PURCHORD:P'))
OR UPPER(transaction.status) IS NULL)
AND UPPER(account.accttype) IN ('COGS',
'DEFEREXPENSE',
'EXPENSE',
'OTHEXPENSE')))
GROUP BY transactionLine.class,
transactionLine.department,
transactionLine.cseg_grant,
transactionLine.cseg_restriction,
transactionLine.cseg_revtype,
transactionLine.cseg1,
transactionLine.cseg_rev_sub,
transactionLine.cseg_timerestrict,
transactionLine.cseg_fun_exp,
transactionLine.cseg_region
Question:
Is there any performance impact if the query has more no of Group by
conditions?
Here in this example, the result return from the query is limited by having the below where conditions. This query can grow as user select different values for the respective column. By doing this way is there going to be any performance impact? Can this query be fine-tuned to improve the query performance?
((transactionLine.department= '11'
AND transactionLine.cseg_grant ='1'
AND transactionLine.class = '12'
AND transactionLine.cseg_restriction = '1'
AND transactionLine.cseg_revtype = '1'
AND transactionLine.cseg1 = '4'
AND transactionLine.cseg_rev_sub = '1'
AND transactionLine.cseg_timerestrict = '1'
AND transactionLine.cseg_fun_exp = '4'
AND transactionLine.cseg_region = '1') OR (transactionLine.department= '12'
AND transactionLine.cseg_grant ='1'
AND transactionLine.class = '12'
AND transactionLine.cseg_restriction = '1'
AND transactionLine.cseg_revtype = '1'
AND transactionLine.cseg1 = '4'
AND transactionLine.cseg_rev_sub = '1'
AND transactionLine.cseg_timerestrict = '1'
AND transactionLine.cseg_fun_exp = '4'
AND transactionLine.cseg_region = '1'))

Query to get worksheet manager hierarchy for a parameter in BI-publisher

The parameter has two values direct reports and indirect report.
I have tried:
select distinct cch.emp_person_id,
cch.lvl_num Empl_Lvl,
cch_lv.lvl_num MGR_LVL
from cmp_cwb_hrchy cch, cmp_cwb_hrchy cch_lv
where cch.mgr_person_id = :Mgr_id and
cch_lv.emp_person_id = :Mgr_id and
cch.MGR_PERSON_EVENT_ID= cch_lv.MGR_PERSON_EVENT_ID and
cch.EMP_PERSON_EVENT_ID = cch_lv.EMP_PERSON_EVENT_ID and
cch.lvl_num = cch_lv.lvl_num and
( 1=1 and cch.lvl_num = case when :direct_ALL = 'Direct' then cch_lv.lvl_num+1 else NULL end) and
( 1=1 and cch.lvl_num > case when :direct_ALL = 'ALL' then cch_.lvl_num else NULL end)

Missing parenthesis for case statement

While running the below SQL I'm getting an error:
Missing parenthesis
SELECT DISTINCT
RPH.transport_mode, PCP.air_export_ind, PCP.air_import_ind
FROM
RATE_PROFILE_HEADER RPH, PARTNER_CHARGE_PROFILE PCP
WHERE
PCP.charge_code = RPH.Charge_code
AND PCP.charge_calculation_method = 'R'
AND RPH.RP_RECORD_ID = PCP.CHARGE_RATEPROF_RECORD_ID
AND CASE '&psTransport_mode'
WHEN 'A'
THEN (DECODE(RPH.transport_mode, 'ALL', 'A', RPH.transport_mode) = 'A') AND (PCP.air_export_ind = 'Y' or PCP.air_import_ind = 'Y')
WHEN 'M'
THEN (DECODE(RPH.transport_mode, 'ALL', 'M', RPH.transport_mode) = 'M') AND (PCP.air_export_ind = 'Y' or PCP.air_import_ind = 'Y')
ELSE NULL
END
I want to pass multiple conditions in THEN for WHERE clause.
Should I have to use an IF statement?
How about not using a CASE statement at all. It seems like you just need a nested conditional:
Select
distinct
RPH.transport_mode,
PCP.air_export_ind,
PCP.air_import_ind
from
RATE_PROFILE_HEADER RPH,
PARTNER_CHARGE_PROFILE PCP
where
PCP.charge_code = RPH.Charge_code
AND PCP.charge_calculation_method = 'R'
AND RPH.RP_RECORD_ID = PCP.CHARGE_RATEPROF_RECORD_ID
AND
(
'&psTransport_mode' = 'A' AND ( Decode(RPH.transport_mode,'ALL','A',RPH.transport_mode) = 'A') AND (PCP.air_export_ind = 'Y' or PCP.air_import_ind = 'Y')
OR
'&psTransport_mode' = 'M' AND ( Decode(RPH.transport_mode,'ALL','M',RPH.transport_mode) = 'M') AND (PCP.air_export_ind = 'Y' or PCP.air_import_ind = 'Y')
)

How to use bitwise operator in existing sql query?

Here is my sql query. I have column name "ExpenseBucketCoverage" in claim table in which I am storing bitwise operators store multiple values in one column like below
MED_COPAY = 1, MED_DED= 10, MED_COINS = 100, RX_COPAY = 1, RX_DED= 10, RX_COINS = 100
I want to replace hard coded value like MED_COPAY, MED_COINS, MED_DED, RX_DED, RX_COINS & RX_COPAY in query by using ExpenseBucketCoverage column value. Can some one please tell me how can I do that?
Someone has suggested me below soultion
retrieve data from claim and left joining the first matched record in eligibility. And then add custom code to loop through the datarows to split the rows by covered expense bucket, and set the service category code in-memory column based on the ExpenseBucketCoverage value for the claim.
SELECT
e.categoryid,
c.servicetype,
'II' AS RepordType,
e.TPAId AS TPA_Id,
e.EmployerCode,
e.SubscriberId,
e.MemberID,
c.ServiceFrom,
c.ServiceTo,
CASE
WHEN e.categoryid IN( 'MED_DED', 'RX_DED' ) THEN
deductible
WHEN e.categoryid IN( 'MED_COINS', 'RX_COINS' ) THEN
isnull(coins,0)
WHEN e.categoryid IN( 'MED_COPAY', 'RX_COPAY' ) THEN
copay
ELSE 0
END AS ClaimAmount,
'' AS AccountTypeCode,
'1' ClaimsCrossoverAutoPay,
e.CategoryId,
CASE c.ServiceType
WHEN 'H' THEN
CASE e.PayeeIndicator
WHEN 'N' THEN '0'
WHEN 'Y' THEN '1'
END
WHEN 'P' THEN '0'
END AS PayProvider,
CASE c.ServiceType
WHEN 'H' THEN
CASE PayeeIndicator
WHEN 'N' THEN '0'
WHEN 'Y' THEN '1'
END
WHEN 'P' THEN '0'
END AS ReimbursementMethod,
CASE c.ServiceType
WHEN 'H' THEN c.Provider
WHEN 'P' THEN ''
END AS ProviderId,
'1' EnforceAccountEffectiveDates,
c.Id,
c.ClaimNumber + e.CategoryId as 'ExternalClaimNumber',
c.ProviderName,
c.CarrierId + ';' + c.SourceClaimNumber AS Notes
FROM Claim c
INNER JOIN Eligibility e ON e.TPAId = c.TPAId AND e.EIN = c.EIN AND
c.Processed = 'Y' AND e.FilterType = 'Eligibility'
AND c.TPAId='PrimePay'
AND (c.ServiceFrom >= e.BenefitEffectiveDate
AND c.ServiceFrom <=e.BenefitTermDate)
AND ( ( c.PayorID = c.PatientSSN
AND e.SubscriberSSN = c.PatientSSN
AND (c.EmployeeFirstName = c.PatientFirstName
AND c.EmployeeLastName = c.PatientLastName)
AND(e.MemberSSN = '' OR e.MemberSSN = NULL)
AND(e.MemberFirstName = '' OR e.MemberFirstName = NULL)
AND(e.MemberLastName = '' OR e.MemberLastName = NULL))
OR((c.PayorID != c.PatientSSN AND e.MemberSSN = c.PatientSSN
AND e.MemberFirstName = c.PatientFirstName
AND e.MemberLastName = c.PatientLastName)
OR(c.PayorID != c.PatientSSN AND e.MemberFirstName = c.PatientFirstName
AND e.MemberLastName= c.PatientLastName)))
AND (( c.Servicetype ='P'
AND e.CategoryID IN('RX_COINS','RX_COPAY', 'RX_DED' ))
OR ( c.Servicetype = 'H'
AND e.CategoryID IN( 'MED_COINS','MED_COPAY', 'MED_DED' )))

Sybase proc throws "Incorrect syntax near '='"

I have the following piece of a SELECT query inside a stored procedure i'm developing:
AND (
CASE S.SWITCH
WHEN 'A' THEN P.TEST = T.OPTION_1
WHEN 'C' THEN P.TEST = T.OPTION_1 + T.OPTION_2
WHEN 'G' THEN P.TEST = T.OPTION_3
WHEN 'N' THEN TRUE
ELSE FALSE
END
)
I'm getting an Incorrect syntax near '=' error. Why would it complain about the first equals sign? It's a Sybase server if anyone is interested.
You case comparison should be something like below, if you are testing P.TEST value based on S.SWITCH case.
AND (
P.TEST =
CASE
WHEN S.SWITCH = 'A' THEN T.OPTION_1
WHEN S.SWITCH = 'C' THEN T.OPTION_1 + T.OPTION_2
WHEN S.SWITCH = 'G' THEN T.OPTION_3
WHEN S.SWITCH = 'N' THEN TRUE
ELSE FALSE
END
)
If you are comparing based on P.TEST and S.SWITCH, you can do either of following
Blorgbeard already provided this answer
AND
(
(S.SWITCH = 'A' AND P.TEST = T.OPTION_1) OR
(S.SWITCH = 'C' AND T.OPTION_1 + T.OPTION_2) OR
(S.SWITCH = 'G' AND P.TEST = T.OPTION_3) OR
(S.SWITCH = 'N')
)
If you want to make case statement work for this, following could be a possible solution.
AND (
CASE 1 =
WHEN S.SWITCH = 'A' AND P.TEST = T.OPTION_1 THEN 1
WHEN S.SWITCH = 'C' AND P.TEST = T.OPTION_1 + T.OPTION_2 THEN 1
WHEN S.SWITCH = 'G' AND P.TEST = T.OPTION_3 THEN 1
WHEN S.SWITCH = 'N' THEN 1
ELSE 0
END
)
Boolean expressions don't work like that in SQL. You can reformulate your switch like this:
AND (
(S.SWITCH = 'A' AND P.TEST = T.OPTION_1) OR
(S.SWITCH = 'C' AND T.OPTION_1 + T.OPTION_2) OR
(S.SWITCH = 'G' AND P.TEST = T.OPTION_3) OR
(S.SWITCH = 'N')
)
I know this is more of a comment than an answer, but hopefully this will lead to an answer, and I need to do formatted code for this so...
I tried this in Mysql and it worked. Could you try something like this in Sybase and see what it returns? The point being, extract the part that failed and test it out and see if you can figure out exactly what is wrong. It may be that Sybase is pointing to that equal sign but something else is really what is confusing it.
set #miller:='C';
set #mtime:=2;
select CASE #miller
WHEN 'A' THEN #mtime = 1
WHEN 'C' THEN #mtime = 2
WHEN 'G' THEN #mtime = 3
WHEN 'N' THEN TRUE
ELSE FALSE
END
This returns a 1 since miller = 'C' takes it to check if mtime = 2, which is true, and that means a 1 or true in Mysql.
Could you try and isolate this bit of code like this in Sybase?