Using Case Statement to Compare and Exclude - case

(Working in Teradata) I've been tasked with comparing the values of any of 3 specific columns to 3 other specific columns. I would include the record if a value from one of the initial 3 specified columns match the value of any of the second set of 3 columns.
Columns
Diag_Prefix, Diag2_Prefix, and Diag3_Prefix
are being compared to
Xref_Diag_Prefix, Xref_Dia2g_Prefix , Xref_Diag2_Prefix
So, as an example, if Diag_Prefix contains value A10 and that value is also contained in Xref_Diag_Prefix, OR Xref_Dia2g_Prefix, OR Xref_Diag2_Prefix then I would keep the record, otherwise I would exclude it.
I believe I have this part down as follows:
AND (CASE WHEN Diag_Prefix = Xref_Diag_Prefix OR Diag_Prefix = Xref_Diag2_Prefix OR Diag_Prefix = Xref_Diag3_Prefix
OR Diag2_Prefix = Xref_Diag_Prefix OR Diag2_Prefix = Xref_Diag2_Prefix OR Diag2_Prefix = Xref_Diag3_Prefix
OR Diag3_Prefix = Xref_Diag_Prefix OR Diag3_Prefix = Xref_Diag2_Prefix OR Diag3_Prefix = Xref_Diag3_Prefix
THEN 'I' ELSE 'E' END) = 'I'
My problem is that some of the values in these columns are 'NULL' and have been populated with the value of 'UNK' in such cases. These records are being included with my CASE statement above, so I'm trying to change the UNK values into something unique for each field, as follows:
/* Converting UNK values to exclude from subsequent comparison case statement */
AND (CASE WHEN Diag_Prefix = 'UNK' THEN 'UNKD1' ELSE Diag_Prefix END)
AND (CASE WHEN Diag2_Prefix = 'UNK' THEN 'UNKD2' ELSE Diag2_Prefix END)
AND (CASE WHEN Diag3_Prefix = 'UNK' THEN 'UNKD3' ELSE Diag3_Prefix END)
AND (CASE WHEN Xref_Diag_Prefix = 'UNK' THEN 'UNKX1' ELSE Xref_Diag_Prefix END)
AND (CASE WHEN Xref_Diag2_Prefix = 'UNK' THEN 'UNKX2' ELSE Xref_Diag2_Prefix END)
AND (CASE WHEN Xref_Diag3_Prefix = 'UNK' THEN 'UNKX3' ELSE Xref_Diag3_Prefix END)
But this is giving me an error that states: "...expected something like a 'SUCCEEDS', 'MEETS', 'PRECEDES', 'IN', or 'CONTAINS' keyword between ')' and the 'AND' keyword."
I'm not sure if it would be easier to just create a VT somehow. Any help would be greatly appreciated.

This seems like it would be easier to do without the CASE statement getting in the way and just ignoring the 'UNK' values entirely:
WHERE
((
Diag_Prefix = Xref_Diag_Prefix
OR Diag_Prefix = Xref_Diag2_Prefix
OR Diag_Prefix = Xref_Diag3_Prefix
) AND Diag_Prefix <> 'UNK')
OR ((
Diag2_Prefix = Xref_Diag_Prefix
OR Diag2_Prefix = Xref_Diag2_Prefix
OR Diag2_Prefix = Xref_Diag3_Prefix
) AND Diag2_Prefix <> 'UNK')
OR ((
Diag3_Prefix = Xref_Diag_Prefix
OR Diag3_Prefix = Xref_Diag2_Prefix
OR Diag3_Prefix = Xref_Diag3_Prefix
) AND Diag3_Prefix <> 'UNK'

Related

- ORA-01407: cannot update ("PSOWNER"."PS_VCHR_LINE_STG"."CLASS_FLD") to NULL Failed SQL stmt: UPDATE

Error Message:- ORA-01407: cannot update ("PSOWNER"."PS_VCHR_LINE_STG"."CLASS_FLD") to NULL Failed SQL stmt: UPDATE
When I am generating the report it is saying NO Success in Peoplesoft.
Below is the code for the Update statement.
Please help me how to overcome this problem.
UPDATE %Table(VCHR_LINE_STG) A
SET A.CLASS_FLD = (
SELECT SUBSTR(DCP_FLD49
,3
,4)
FROM %Table(DCP_AP11_TMP2)
WHERE VCHR_BLD_KEY_C1 = A.VCHR_BLD_KEY_C1
AND DCP_FLD34= A.VOUCHER_LINE_NUM),A.BUSINESS_UNIT =(
SELECT D.CF_ATTRIB_VALUE
FROM %Table(CF_ATTRIB_TBL) D
, %Table(DEPT_TBL) E
WHERE ( D.EFFDT = (
SELECT MAX(D_ED.EFFDT)
FROM %Table(CF_ATTRIB_TBL) D_ED
WHERE D.SETID = D_ED.SETID
AND D.CHARTFIELD_VALUE = D_ED.CHARTFIELD_VALUE
AND D_ED.EFFDT <= SYSDATE)
AND E.EFFDT=D.EFFDT
AND D.CHARTFIELD_VALUE = (
SELECT M.DCP_FLD41
FROM %Table(DCP_AP11_TMP2) M
WHERE M.VCHR_BLD_KEY_C1 = A.VCHR_BLD_KEY_C1
AND M.DCP_FLD34= A.VOUCHER_LINE_NUM)
AND D.SETID = E.SETID
AND D.SETID = 'DCPID'
AND D.CF_ATTRIBUTE='AP_BUSN_UNIT'
AND E.EFFDT = (
SELECT MAX(E_ED.EFFDT)
FROM %Table(DEPT_TBL) E_ED
WHERE E.SETID = E_ED.SETID
AND E.DEPTID = E_ED.DEPTID
AND E_ED.EFFDT <= SYSDATE)
AND E.DEPTID = D.CHARTFIELD_VALUE
AND E.SETID = D.SETID
AND E.EFF_STATUS='A')),A.BUSINESS_UNIT_GL=(
SELECT D.CF_ATTRIB_VALUE
FROM %Table(CF_ATTRIB_TBL) D
, %Table(DEPT_TBL) E
WHERE ( D.EFFDT = (
SELECT MAX(D_ED.EFFDT)
FROM %Table(CF_ATTRIB_TBL) D_ED
WHERE D.SETID = D_ED.SETID
AND D.CHARTFIELD_VALUE = D_ED.CHARTFIELD_VALUE
AND D_ED.EFFDT <= SYSDATE)
AND E.EFFDT=D.EFFDT
AND D.CHARTFIELD_VALUE = (
SELECT M.DCP_FLD41
FROM %Table(DCP_AP11_TMP2) M
WHERE M.VCHR_BLD_KEY_C1 = A.VCHR_BLD_KEY_C1
AND M.DCP_FLD34= A.VOUCHER_LINE_NUM)
AND D.SETID = E.SETID
AND D.SETID = 'DCPID'
AND D.CF_ATTRIBUTE='GL_BUSN_UNIT'
AND E.EFFDT = (
SELECT MAX(E_ED.EFFDT)
FROM %Table(DEPT_TBL) E_ED
WHERE E.SETID = E_ED.SETID
AND E.DEPTID = E_ED.DEPTID
AND E_ED.EFFDT <= SYSDATE)
AND E.DEPTID = D.CHARTFIELD_VALUE
AND E.SETID = D.SETID
AND E.EFF_STATUS='A'))
WHERE EXISTS (
SELECT 'X'
FROM %Table(DCP_AP11_TMP2)
WHERE VCHR_BLD_KEY_C1 = A.VCHR_BLD_KEY_C1
AND VOUCHER_LINE_NUM = A.VOUCHER_LINE_NUM)
Above is the code for the Update statement in App engine.
Please help me how to overcome this problem.
Thanks in Advance.
The sub-selects populating each field are not returning values so the database is trying to update the field to NULL. In PeopleSoft null values are not allowed in character fields. A field with no value needs to be set to a single space, like ' '.
You will need to wrap each sub-select with a COALESCE() function, with a non-null alternative option if the sub-select does not return a value. Character fields need to be set to ' ', numbers to 0 if no values returned. Date fields can be null. Here is an example using the first few lines of the code provided.
UPDATE %Table(VCHR_LINE_STG) A
SET A.CLASS_FLD =
COALESCE(
(SELECT SUBSTR(DCP_FLD49,3,4)
FROM %Table(DCP_AP11_TMP2)
WHERE VCHR_BLD_KEY_C1 = A.VCHR_BLD_KEY_C1
AND DCP_FLD34= A.VOUCHER_LINE_NUM), ' ')
, A.BUSINESS_UNIT_GL=(SELECT
...

MS SQL Case in Where Clause testing against NULL or Argument

I have a query against a UDF where I want to allow the user to pass in either ALL or a specific EType.
If they pass in ALL, I want to accept all ETypes where it is not null.
I have searched thru SO for examples and not seem to meet my particular situation.
Where am I going wrong?
Declare
#company varchar(4),
#charge_cov bit,
#EType varchar(8);
set #company = '123'
set #charge_cov =1
set #EType = 'ALL'
select e.emp_id,
dbo.format_emp_number(pd.EN) as EN,
dbo.format_emp_number(pd.MEN) as MEN,
pd.EType
from dbo.employee_payroll_data(NULL) pd
inner join employee e on (e.emp_id=pd.emp_id)
where pd.EType = case when #EType='ALL' then pd.EType
else #EType ) END
and pd.EType is not null
and e.emp_number is not null
and e.charge_cov = 1
and lc.pr_co_code = #company
Try below code:
WHERE (((1 = (CASE WHEN #EType = 'ALL' THEN 1 ELSE 0 END)))
OR ((pd.Etype = (CASE WHEN #EType <> 'ALL' THEN #EType ELSE '' END))))
AND pd.Etype IS NOT NULL

Being DRY in a Sqlite query with CASE statement

In the following (working) query:
SELECT q.id, q.section_id, q.type, q.required, q.condition,
CASE WHEN (t1.text_1 IS NULL) THEN
CASE WHEN ((SELECT t2.text_1 FROM translations t2 WHERE t2.item_id = q.id AND t2.item_model = 'questions' AND t2.language = 'en' LIMIT 1) IS NULL) THEN
(SELECT t3.text_1 FROM translations t3 WHERE t3.item_id = q.id AND t3.item_model = 'questions' LIMIT 1)
ELSE
(SELECT t2.text_1 FROM translations t2 WHERE t2.item_id = q.id AND t2.item_model = 'questions' AND t2.language = 'en' LIMIT 1)
END
ELSE
t1.text_1
END
AS translation
FROM questions q
LEFT JOIN translations t1 ON t1.item_id = q.id
AND t1.item_model = 'questions'
AND t1.language = 'fr'
ORDER BY q.position
You can see that the part (SELECT t2.text_1 FROM translations t2 WHERE t2.item_id = q.id AND t2.item_model = 'questions' AND t2.language = 'en' LIMIT 1) is repeated twice (the first to check if it's null, and the second to get the value).
Could the repeated same query a performance issue (I guess so)?
Is there a better way to rewrite this query, being DRY?
You can replace the inner CASE statement with coalesce() function:
coalesce(SELECT t2.text_1 FROM translations t2 WHERE t2.item_id = q.id AND t2.item_model = 'questions' AND t2.language = 'en' LIMIT 1,
SELECT t3.text_1 FROM translations t3 WHERE t3.item_id = q.id AND t3.item_model = 'questions' LIMIT 1)
From the documenation:
coalesce(X,Y,...)
The coalesce() function returns a copy of its first non-NULL argument,
or NULL if all arguments are NULL. Coalesce() must have at least 2
arguments.
Similar is the ifnull() function.

Subquery with sum function to pull in multiple records

SubQuery pulling in the same record in the "ON_ORDER" column. I want the query to pull in the ON_ORDER qty per Item. Can someone please show me what I am not doing right? I have been on this for quite awhile.
SELECT
N.SITEID,
C.LOCATION,
(I.EX2AREARESP||I.EX2STDSTS||I.EX2APPTYPE) AS STD,
I.ITEMNUM,
I.COMMODITY,
I.COMMODITYGROUP,
I.DESCRIPTION,
I.ISSUEUNIT,
C.AVGCOST,
SUM(NVL(B.CURBAL,0)) AS CURBAL,
NVL(SUM(D.SHIPPEDQTY),0) AS IN_TRANSIT,
(
SELECT
SUM(PL.ORDERQTY - NVL(PL.RECEIVEDQTY,0))
FROM MSCRADS.PO P,
MSCRADS.POLINE PL,
MXRADS.ITEM I
WHERE P.PONUM = PL.PONUM
AND PL.LINETYPE = 'ITEM'
AND P.RECEIPTS <> 'COMPLETE'
AND PL.ITEMNUM = I.ITEMNUM
AND P.ORDERDATE >= TO_DATE('2014/05/26','YYYY/MM/DD')
AND PL.RECEIPTSCOMPLETE = '0'
AND P.INTERNAL = '0'
AND PL.ISSUE = '0'
AND P.STATUS NOT IN ('COMPLETE','CLOSE','CAN')
AND P.SITEID <> 'MS'
AND P.REVISIONNUM = PL.REVISIONNUM
AND (P.HISTORYFLAG = '0' OR (P.HISTORYFLAG = '1'
AND P.STATUS = 'CLOSE' AND PL.RECEIVEDQTY > '0'))
AND NOT (P.STATUS = 'COMPLETE'
AND (PL.RECEIVEDQTY = '0' OR PL.RECEIVEDQTY IS NULL))
) AS "ON_ORDER",
NVL(SUM(CASE WHEN D.RESTYPE = 'APSOFT' THEN D.RESERVEDQTY
ELSE NULL END),0) AS "ALLOCATED",
NVL(SUM(CASE WHEN D.RESTYPE = 'APHARD' THEN D.RESERVEDQTY
ELSE NULL END),0) AS "RESERVE",
N.MINLEVEL AS ROP,
N.ORDERQTY AS EOQ,
N.DELIVERYTIME AS LEADTIME,
NVL(N.SSTOCK,0) "SAFETY STOCK",
CASE N.REORDER WHEN 1 THEN 'AUTO_RE-ORDER'
WHEN 0 THEN 'MANUAL_RE-ORDER'
ELSE ' '
END AS "REORDER PROCESS",
N.STATUS "INVENTORY STATUS"
FROM MXRADS.INVENTORY N
LEFT OUTER JOIN
MXRADS.ITEM I
ON I.ITEMNUM = N.ITEMNUM
LEFT OUTER JOIN
MSCRADS.INVCOST C
ON N.ITEMNUM = C.ITEMNUM
AND N.LOCATION = C.LOCATION
LEFT OUTER JOIN
MSCRADS.INVBALANCES B
ON N.ITEMNUM = B.ITEMNUM
AND N.LOCATION = B.LOCATION
LEFT OUTER JOIN
MSCRADS.INVRESERVE D
ON N.ITEMNUM = D.ITEMNUM
AND N.LOCATION = D.LOCATION
WHERE N.SITEID <> 'MS'
AND N.LOCATION = '&WHSE'
AND N.STATUS = 'ACTIVE'
--AND N.ITEMNUM = '505611'
GROUP BY
N.SITEID,
C.LOCATION,
(I.EX2AREARESP||I.EX2STDSTS||I.EX2APPTYPE),
I.ITEMNUM,
I.COMMODITY,
I.COMMODITYGROUP,
I.DESCRIPTION,
I.ISSUEUNIT,
C.AVGCOST,
N.MINLEVEL,
N.ORDERQTY,
N.DELIVERYTIME,
N.SSTOCK,
N.REORDER,
N.STATUS
ORDER BY 4

combine multiple queries into single query

I have 2 queries and calling a function 2 times I need call the function one time only based on msg_sys_no count and msg_trans_type.
please find the queries mentioned below and provide me the solution for merging into single.
SELECT COUNT(DISTINCT b1.msg_sys_no) INTO A
FROM tra_message b1
WHERE TO_CHAR(b1.msg_when_created,'YYYY-MM-DD') = in_start_date
AND b1.msg_service_provider = in_svc_provider
AND b1.msg_trans_type = 'TRADE1'
AND get_transaction_status_func(b1.msg_sys_no, b1.msg_trans_type) = 'S';
SELECT COUNT(DISTINCT b1.msg_sys_no) INTO B
FROM tra_message b1
WHERE TO_CHAR(b1.msg_when_created,'YYYY-MM-DD') = in_start_date
AND b1.msg_service_provider = in_svc_provider
AND b1.msg_trans_type = 'TRADE2'
AND get_transaction_status_func(b1.msg_sys_no, b1.msg_trans_type) = 'S';
What about something like this:
WITH tra_data
AS (SELECT *
FROM tra_message
WHERE TO_CHAR (msg_when_created, 'YYYY-MM-DD') = in_start_date
AND msg_service_provider = in_svc_provider
AND get_transaction_status_func (msg_sys_no, msg_trans_type) =
'S')
SELECT COUNT (*)
FROM tra_data
WHERE msg_trans_type = 'TRADE1'
UNION
SELECT COUNT (*)
FROM tra_data
WHERE msg_trans_type = 'TRADE2'
The problem is your AND b1.msg_trans_type IN ('TRADE1','TRADE2') condition.
Try something like this:
select COUNT(DISTINCT a) TRADE1,
COUNT(DISTINCT b) TRADE2
into A,B
from (
select case when b1.msg_trans_type = 'TRADE1'
then b1.msg_sys_no
else null end as a,
case when b1.msg_trans_type = 'TRADE2'
then b1.msg_sys_no
else null end as b
FROM tra_message b1
WHERE TO_CHAR(b1.msg_when_created,'YYYY-MM-DD') = in_start_date
AND b1.msg_service_provider = in_svc_provider
AND b1.msg_trans_type IN ('TRADE1','TRADE2')
AND get_transaction_status_func(b1.msg_sys_no, b1.msg_trans_type) = 'S'
);

Resources