How to improve SQL query when conditions grows dynamically - sql

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'))

Related

SQL query with multiple OR condition inside AND returns null or empty

I'm trying to get those members who are going to match my filter criteria, but I am passing multiple OR condition inside the round brackets, and every condition which is inside the round brackets is, AND with another round bracket; however, the query does not work, and it returns an empty table, but whensoever I run the query with INTERSECT statement it returns the members. Still, it has been taking 3 seconds on 1 million records, and it is a very cost-paying operation on the server-side, and it will increase if the records increase. Could someone help me why my first query is not working or if I use the second query, is there any way to attenuate the time?
My actual table
First Query, which returns Empty table
SELECT custom_attribute_values.attributable_id as Member_id FROM custom_attribute_values
WHERE (("custom_attribute_id" = '12' AND "value_string" = 'Female') OR ("custom_attribute_id" = '12' AND "value_string" = 'Male'))
AND (("custom_attribute_id" = '17' AND "value_string" = 'Widowed') OR
("custom_attribute_id" = '17' AND "value_string" = 'Divorced') OR ("custom_attribute_id" = '17' AND "value_string" = 'Never married') OR
("custom_attribute_id" = '17' AND "value_string" = 'Married') OR ("custom_attribute_id" = '17' AND "value_string" = 'Separated'))
Second Query, which returns the result in, which I am interested but taking too much time
SELECT custom_attribute_values.attributable_id FROM custom_attribute_values
WHERE (("custom_attribute_id" = '12' AND "value_string" = 'Female') OR ("custom_attribute_id" = '12' AND "value_string" = 'Male'))
INTERSECT
SELECT custom_attribute_values.attributable_id FROM custom_attribute_values WHERE (("custom_attribute_id" = '17' AND "value_string" = 'Widowed') OR
("custom_attribute_id" = '17' AND "value_string" = 'Divorced') OR ("custom_attribute_id" = '17' AND "value_string" = 'Never married') OR
("custom_attribute_id" = '17' AND "value_string" = 'Married') OR ("custom_attribute_id" = '17' AND "value_string" = 'Separated'))
You have conflicting conditions on each row. I'm pretty sure you want aggregation:
SELECT cav.attributable_id as Member_id
FROM custom_attribute_values cav
WHERE ("custom_attribute_id" = '12' AND "value_string" IN ('Female', 'Male')) OR
("custom_attribute_id" = '17' AND "value_string" IN ('Widowed', 'Divorced', 'Never married', 'Married', 'Separated')
)
GROUP BY cav.attributable_id
HAVING COUNT(DISTINCT "custom_attribute_id") = 2; -- both match
The WHERE checks that either condition match. The HAVING validates that both match for a given member.
Note that you should avoid double quotes for identifiers. They just make queries harder to write and to read.

Nested CASE statement in UPDATE SET clause

I am attempting to switch a value based on a set of conditions and I have noticed that where I have a nested CASE statement within the SET clause of my UPDATE expression, the columns are not updating.
When a simple CASE expression existis the columns appear to be updating. However, for the OVERRIDDEN_CHECK_NUMBER and OVERRIDDEN_AMOUNT in this example, the columns are not updating.
The OVERRIDDEN_DATE, OVERRIDDEN_USER_ID, CHECK_NO and AMOUNT columns in the UPDATE are updating without issue.
Can anyone tell me why the OVERRIDDEN_CHECK_NUMBER and OVERRIDDEN_AMOUNT will not update in this UPDATE statement?
Are nested CASE statements not tallowed in the SET clause of the UPDATE expression?
SQL EXAMPLE
UPDATE WAREHOUSE.BANK_STATEMENT_ACTIVITY
SET OVERRIDDEN_CHECK_NO = --(CASE :btn
(CASE WHEN (:btn = '1') THEN CASE WHEN '141973' = '141973' THEN NULL
WHEN '141973' != '999999' THEN LPAD(TRIM(141973), 12, '0')
END
WHEN (:btn = '2') THEN '1740 - Previously Paid Warrant'
ELSE NULL
END),
OVERRIDDEN_AMOUNT = --(CASE :btn
(CASE WHEN (:btn = '1') THEN CASE WHEN 253.20 = 253.20 THEN NULL
WHEN 253.20 != 999.99 THEN LPAD(TRIM(253.20), 12, '0')
END
WHEN (:btn = '2') THEN NULL
ELSE NULL
END),
OVERRIDDEN_DATE = SYSDATE,
OVERRIDDEN_USER_ID = 1009,
CHECK_NO = (CASE :btn
WHEN '1' THEN LPAD(TRIM(999999), 12, '0')
WHEN '2' THEN '142775'
ELSE NULL
END),
AMOUNT = (CASE :btn
WHEN '1' THEN TRIM(78.60)
WHEN '2' THEN TRIM(253.20)
ELSE NULL
END)
WHERE TO_NUMBER(CHECK_NO) = (CASE :btn
WHEN '1' THEN '141973'
WHEN '2' THEN '142775'
ELSE NULL
END)
AND AMOUNT = (CASE :btn
WHEN '1' THEN 78.60
WHEN '2' THEN 253.20
ELSE NULL
END)
AND TRUNC(LOAD_DATE) = (CASE :btn
WHEN '1' THEN TRUNC(LOAD_DATE)
WHEN '2' THEN (SELECT (MAX(LOAD_DATE)) FROM WAREHOUSE.BANK_STATEMENT_ACTIVITY)
ELSE NULL
END)
AND BANKACCTNO = (SELECT LONGDESC
FROM TCMS.COMPLEMENTARY_VALIDATIONS
WHERE TEXTCODE = 'BANKACCT'
AND CODE = 80);
EDIT
After fixing the logival issue that #mathguy pointed out the update query via the editor worked. However, when executing this via the PL/SQL pacakge the table update fails.
Here is the before update:
Before - result
Her is the after result:
After - result
They are identical.
This is the actual package procedure:
PROCEDURE UpdateBankStatementActivity( btn IN VARCHAR2)
AS
BEGIN
DBMS_OUTPUT.PUT_LINE( 'UpdateBankStatementActivity - btn: ' || btn );
DBMS_OUTPUT.PUT_LINE( 'UpdateBankStatementActivity - bsa_rec.OVERRIDDEN_CHECK_NO: ' || bsa_rec.OVERRIDDEN_CHECK_NO || CHR(10) ||
'bsa_rec.OVERRIDDEN_AMOUNT: ' || bsa_rec.OVERRIDDEN_AMOUNT || CHR(10) ||
'bsa_rec.CHECK_NO: ' || bsa_rec.CHECK_NO || CHR(10) ||
'bsa_rec.AMOUNT: ' || bsa_rec.AMOUNT || CHR(10) ||
'bsa_rec.LOAD_DATE:' || bsa_rec.LOAD_DATE );
UPDATE WAREHOUSE.BANK_STATEMENT_ACTIVITY
SET OVERRIDDEN_CHECK_NO = --(CASE :btn
(CASE WHEN (btn = '1') THEN CASE WHEN bsa_rec.OVERRIDDEN_CHECK_NO = bsa_rec.CHECK_NO THEN NULL
WHEN bsa_rec.OVERRIDDEN_CHECK_NO != bsa_rec.CHECK_NO THEN LPAD(TRIM(bsa_rec.OVERRIDDEN_CHECK_NO), 12, '0')
END
WHEN (btn = '2') THEN '1740 - Previously Paid Warrant'
ELSE NULL
END),
OVERRIDDEN_AMOUNT = --(CASE :btn
(CASE WHEN (btn = '1') THEN CASE WHEN bsa_rec.OVERRIDDEN_AMOUNT = bsa_rec.AMOUNT THEN NULL
WHEN bsa_rec.OVERRIDDEN_AMOUNT != bsa_rec.AMOUNT THEN LPAD(TRIM(bsa_rec.OVERRIDDEN_AMOUNT), 12, '0')
END
WHEN (btn = '2') THEN NULL
ELSE NULL
END),
OVERRIDDEN_DATE = SYSDATE,
OVERRIDDEN_USER_ID = bsa_rec.OVERRIDDEN_USER_ID,
CHECK_NO = (CASE btn
WHEN '1' THEN LPAD(TRIM(bsa_rec.CHECK_NO), 12, '0')
WHEN '2' THEN LPAD(TRIM(bsa_rec.CHECK_NO), 12, '0')
ELSE NULL
END),
AMOUNT = (CASE btn
WHEN '1' THEN TRIM(bsa_rec.OVERRIDDEN_AMOUNT)
WHEN '2' THEN TRIM(bsa_rec.AMOUNT)
ELSE NULL
END)
WHERE TO_NUMBER(CHECK_NO) = (CASE btn
WHEN '1' THEN bsa_rec.OVERRIDDEN_CHECK_NO
WHEN '2' THEN bsa_rec.CHECK_NO
ELSE NULL
END)
AND AMOUNT = (CASE btn
WHEN '1' THEN bsa_rec.OVERRIDDEN_AMOUNT
WHEN '2' THEN bsa_rec.AMOUNT
ELSE NULL
END)
AND TRUNC(LOAD_DATE) = (CASE btn
WHEN '1' THEN TRUNC(bsa_rec.LOAD_DATE)
WHEN '2' THEN (SELECT MAX(LOAD_DATE) FROM WAREHOUSE.BANK_STATEMENT_ACTIVITY)
ELSE NULL
END)
AND BANKACCTNO = (SELECT LONGDESC
FROM TCMS.COMPLEMENTARY_VALIDATIONS
WHERE TEXTCODE = 'BANKACCT'
AND CODE = 80);
COMMIT;
END UpdateBankStatementActivity;
The parameter values in the first SQL CODE snippet are consistent with the parameters in the PL/SQL block.
What do you mean by "not updating"?
There is a clear logical flaw in your nested case expressions, when :btn = '1'. Namely, the first branch of the "inner" case expression always evaluates to TRUE, so the "update value" will be null every time you pass in :btn = '1'. Is that the problem you are noticing? Then: For overridden_amount the result will always be null because of this; for overridden_check_no it will not be null if and only if :btn = '2'.
Note that you could write the "outer" case expressions with the same syntax you use for the simple expressions: case :btn when '1' then case .... end else ... end.
EDIT: Answering your modified question (perhaps). I am not sure I can follow the logic in its entirety; but what is happening in the example (assuming you called the procedure with btn = '1' is this:
Both the overridden_check_no and the overridden_amount are null in the original table. In the nested (inner) case expression for both columns you check two columns, with either = or !=. Neither of the tests is true when one of the terms is null! So the case evaluations falls through to the else clause, or when else is not included, to the default, which is null. The update actually did work, it just updated the values to null because none of the "actual branches" in the inner case statements evaluated to true.
You say, though, that this works OK if you just run it as a stand-alone SQL update, directly from your editor. I wonder how that is possible, unless - again - the code in the procedure is different from what you have in your editor.

Is it better to JOIN using OR in the join condition or to use multiple JOINS

I'm trying to flag tickets based on whether they indicate a certain event has occurred. The issue I'm running into is that the particular value(s) that indicate such a condition occurred could be in any 1 of 25 fields on the ticket and my current logic takes quite a while to complete (generally >45min) if it completes at all (our DBAs ocassionally kill it for taking too much CPU or having too high a PJI). Currently I'm using the below to try and flag the tickets:
CREATE VOLATILE TABLE
--DROP TABLE
FCT
AS (
SELECT
I_FCT.Ticket_Nbr
, I_FCT.Plan_Dim_CK
, I_FCT.S_DATE
, I_FCT.E_DATE
, CASE
WHEN I_FCT.Event1_CK = AD.Event_CK THEN '1'
WHEN I_FCT.Event2_CK = AD.Event_CK THEN '2'
WHEN I_FCT.Event3_CK = AD.Event_CK THEN '3'
WHEN I_FCT.Event4_CK = AD.Event_CK THEN '4'
WHEN I_FCT.Event5_CK = AD.Event_CK THEN '5'
WHEN I_FCT.Event6_CK = AD.Event_CK THEN '6'
WHEN I_FCT.Event7_CK = AD.Event_CK THEN '7'
WHEN I_FCT.Event8_CK = AD.Event_CK THEN '8'
WHEN I_FCT.Event9_CK = AD.Event_CK THEN '9'
WHEN I_FCT.Event10_CK = AD.Event_CK THEN '10'
WHEN I_FCT.Event11_CK = AD.Event_CK THEN '11'
WHEN I_FCT.Event12_CK = AD.Event_CK THEN '12'
WHEN I_FCT.Event13_CK = AD.Event_CK THEN '13'
WHEN I_FCT.Event14_CK = AD.Event_CK THEN '14'
WHEN I_FCT.Event15_CK = AD.Event_CK THEN '15'
/*WHEN I_FCT.Event16_CK = AD.Event_CK THEN '16'
WHEN I_FCT.Event17_CK = AD.Event_CK THEN '17'
WHEN I_FCT.Event18_CK = AD.Event_CK THEN '18'
WHEN I_FCT.Event19_CK = AD.Event_CK THEN '19'
WHEN I_FCT.Event20_CK = AD.Event_CK THEN '20'
WHEN I_FCT.Event21_CK = AD.Event_CK THEN '21'
WHEN I_FCT.Event22_CK = AD.Event_CK THEN '22'
WHEN I_FCT.Event23_CK = AD.Event_CK THEN '23'
WHEN I_FCT.Event24_CK = AD.Event_CK THEN '24'
WHEN I_FCT.Event25_CK = AD.Event_CK THEN '25'*/
ELSE NULL
END AS AOD_Event
FROM
I_FCT
LEFT JOIN AOD_CKS AS AD
ON (AD.Event_CK = I_FCT.Event1_CK
OR AD.Event_CK = I_FCT.Event2_CK
OR AD.Event_CK = I_FCT.Event3_CK
OR AD.Event_CK = I_FCT.Event4_CK
OR AD.Event_CK = I_FCT.Event5_CK
OR AD.Event_CK = I_FCT.Event6_CK
OR AD.Event_CK = I_FCT.Event7_CK
OR AD.Event_CK = I_FCT.Event8_CK
OR AD.Event_CK = I_FCT.Event9_CK
OR AD.Event_CK = I_FCT.Event10_CK
OR AD.Event_CK = I_FCT.Event11_CK
OR AD.Event_CK = I_FCT.Event12_CK
OR AD.Event_CK = I_FCT.Event13_CK
OR AD.Event_CK = I_FCT.Event14_CK
OR AD.Event_CK = I_FCT.Event15_CK
/*OR AD.Event_CK = I_FCT.Event16_CK
OR AD.Event_CK = I_FCT.Event17_CK
OR AD.Event_CK = I_FCT.Event18_CK
OR AD.Event_CK = I_FCT.Event19_CK
OR AD.Event_CK = I_FCT.Event20_CK
OR AD.Event_CK = I_FCT.Event21_CK
OR AD.Event_CK = I_FCT.Event22_CK
OR AD.Event_CK = I_FCT.Event23_CK
OR AD.Event_CK = I_FCT.Event24_CK
OR AD.Event_CK = I_FCT.Event25_CK*/
)
)
WITH DATA PRIMARY INDEX (Ticket_Nbr)
ON COMMIT PRESERVE ROWS;
So my question is whether it would be better to switch to JOINing once per Event CK (which is a key value by the way & is the index on AOD_CKS)? Or should I go a little less verbose & try splitting up the work (i.e. join once for fields 1-6, another table for 7-13, etc.) & then JOIN those 4 tables together?
Any help is much appreciated!
I ended up splitting the JOIN into 3 pieces and then merging the data as follows:
----------------------------------------------------------------------------
-- FLAG ADDICTION CLAIMS
----------------------------------------------------------------------------
CREATE VOLATILE TABLE
--DROP TABLE
I_FCT_1
AS (
SELECT
I_FCT.Claim_Nbr
, I_FCT.Plan_Dim_CK
, CASE
WHEN I_FCT.Diag1_CK = AD.Diag_CK THEN '1'
WHEN I_FCT.Diag2_CK = AD.Diag_CK THEN '2'
WHEN I_FCT.Diag3_CK = AD.Diag_CK THEN '3'
WHEN I_FCT.Diag4_CK = AD.Diag_CK THEN '4'
WHEN I_FCT.Diag5_CK = AD.Diag_CK THEN '5'
WHEN I_FCT.Diag6_CK = AD.Diag_CK THEN '6'
WHEN I_FCT.Diag7_CK = AD.Diag_CK THEN '7'
WHEN I_FCT.Diag8_CK = AD.Diag_CK THEN '8'
ELSE NULL
END AS AOD_Diag
FROM
I_FCT
LEFT JOIN ADD_CKS AS AD
ON (AD.Diag_CK = I_FCT.Diag1_CK
OR AD.Diag_CK = I_FCT.Diag2_CK
OR AD.Diag_CK = I_FCT.Diag3_CK
OR AD.Diag_CK = I_FCT.Diag4_CK
OR AD.Diag_CK = I_FCT.Diag5_CK
OR AD.Diag_CK = I_FCT.Diag6_CK
OR AD.Diag_CK = I_FCT.Diag7_CK
OR AD.Diag_CK = I_FCT.Diag8_CK
)
)
WITH DATA PRIMARY INDEX (Claim_Nbr)
ON COMMIT PRESERVE ROWS;
----------------------------------------------------------------------------
CREATE VOLATILE TABLE
--DROP TABLE
I_FCT_2
AS (
SELECT
I_FCT.Claim_Nbr
, I_FCT.Plan_Dim_CK
, CASE
WHEN I_FCT.Diag9_CK = AD.Diag_CK THEN '9'
WHEN I_FCT.Diag10_CK = AD.Diag_CK THEN '10'
WHEN I_FCT.Diag11_CK = AD.Diag_CK THEN '11'
WHEN I_FCT.Diag12_CK = AD.Diag_CK THEN '12'
WHEN I_FCT.Diag13_CK = AD.Diag_CK THEN '13'
WHEN I_FCT.Diag14_CK = AD.Diag_CK THEN '14'
WHEN I_FCT.Diag15_CK = AD.Diag_CK THEN '15'
WHEN I_FCT.Diag16_CK = AD.Diag_CK THEN '16'
ELSE NULL
END AS AOD_Diag
FROM
I_FCT
LEFT JOIN ADD_CKS AS AD
ON (AD.Diag_CK = I_FCT.Diag9_CK
OR AD.Diag_CK = I_FCT.Diag10_CK
OR AD.Diag_CK = I_FCT.Diag11_CK
OR AD.Diag_CK = I_FCT.Diag12_CK
OR AD.Diag_CK = I_FCT.Diag13_CK
OR AD.Diag_CK = I_FCT.Diag14_CK
OR AD.Diag_CK = I_FCT.Diag15_CK
OR AD.Diag_CK = I_FCT.Diag16_CK
)
)
WITH DATA PRIMARY INDEX (Claim_Nbr)
ON COMMIT PRESERVE ROWS;
----------------------------------------------------------------------------
CREATE VOLATILE TABLE
--DROP TABLE
I_FCT_3
AS (
SELECT
I_FCT.Claim_Nbr
, I_FCT.Plan_Dim_CK
, CASE
WHEN I_FCT.Diag17_CK = AD.Diag_CK THEN '17'
WHEN I_FCT.Diag18_CK = AD.Diag_CK THEN '18'
WHEN I_FCT.Diag19_CK = AD.Diag_CK THEN '19'
WHEN I_FCT.Diag20_CK = AD.Diag_CK THEN '20'
WHEN I_FCT.Diag21_CK = AD.Diag_CK THEN '21'
WHEN I_FCT.Diag22_CK = AD.Diag_CK THEN '22'
WHEN I_FCT.Diag23_CK = AD.Diag_CK THEN '23'
WHEN I_FCT.Diag24_CK = AD.Diag_CK THEN '24'
WHEN I_FCT.Diag25_CK = AD.Diag_CK THEN '25'
ELSE NULL
END AS AOD_Diag
FROM
I_FCT
LEFT JOIN ADD_CKS AS AD
ON (AD.Diag_CK = I_FCT.Diag17_CK
OR AD.Diag_CK = I_FCT.Diag18_CK
OR AD.Diag_CK = I_FCT.Diag19_CK
OR AD.Diag_CK = I_FCT.Diag20_CK
OR AD.Diag_CK = I_FCT.Diag21_CK
OR AD.Diag_CK = I_FCT.Diag22_CK
OR AD.Diag_CK = I_FCT.Diag23_CK
OR AD.Diag_CK = I_FCT.Diag24_CK
OR AD.Diag_CK = I_FCT.Diag25_CK
)
)
WITH DATA PRIMARY INDEX (Claim_Nbr)
ON COMMIT PRESERVE ROWS;
---------------------------------------------------------------------------
CREATE VOLATILE TABLE
--DROP TABLE
FCT
AS (
SELECT
I_FCT.Claim_Nbr
, I_FCT.Plan_Dim_CK
, I_FCT.ADMISSION_DATE
, I_FCT.DISCHARGE_DATE
, I_FCT.ADMISSION_DATE_DIM_CK
, I_FCT.Proc3_CK
, I_FCT.Proc4_CK
, I_FCT.Proc5_CK
, I_FCT.Proc6_CK
, I_FCT.Proc7_CK
, I_FCT.Bill_Type
, CASE
WHEN C1.AOD_Diag IS NOT NULL THEN C1.AOD_Diag
WHEN C2.AOD_Diag IS NOT NULL THEN C2.AOD_Diag
WHEN C3.AOD_Diag IS NOT NULL THEN C3.AOD_Diag
ELSE NULL
END AS AOD_Diag
FROM
I_FCT
JOIN I_FCT_1 AS C1
ON C1.Claim_Nbr = I_FCT.Claim_Nbr
AND C1.Plan_Dim_CK = I_FCT.Plan_Dim_CK
JOIN I_FCT_2 AS C2
ON I_FCT.Claim_Nbr = C2.Claim_Nbr
AND I_FCT.Plan_Dim_CK = C2.Plan_Dim_CK
JOIN I_FCT_3 AS C3
ON I_FCT.Claim_Nbr = C3.Claim_Nbr
AND I_FCT.Plan_Dim_CK = C3.Plan_Dim_CK
)
WITH DATA PRIMARY INDEX (Claim_Nbr)
ON COMMIT PRESERVE ROWS;

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' )))

SQL Query changing based on parameters

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'))