case statement with in case statement - oracle

I am not sure what kind of statement I need in order for what i need to do. I would like to add a case statement after the case statement i currently have. Bellow is the case statement.
CASE
WHEN LOCOFF.EXT_SRV_POLYGON IN ('BOF', 'CDA', 'COL', 'DAC', 'GOS', 'KEL', 'KLF', 'LAG', 'LEC', 'MED', 'PUM', 'RIT', 'ROS', 'SAN', 'SPO')
THEN 'GAS'
WHEN LOCOFF.EXT_SRV_POLYGON IN ('CDC', 'COC', 'DAV', 'DPC', 'GRC', 'KEC', 'LCC', 'OTC', 'PAC', 'SAC', 'SPC')
THEN 'ELECTRIC'
ELSE 'MISSING'
END AS TYPE,
I would like to say if EXT_Distworktype is GC or GT and the TYPE is ELECTRIC,
GIVE ME TYPE THAT SAYS WRONG POLYGON OR IF THE EXT_DISTWORKTYPE is EC, ES, or ET and Type is GAS then give me a TYPE that say WRONG POLYGON.
here is my full query:
SELECT WO.WONUM AS "Work Order",
WO.LOCATION AS "Location",
WO.STATUS AS "Status",
WO.DESCRIPTION,
WO.ACTFINISH AS "Actual Finish",
WO.PARENT AS "Parent WO",
WO.WORKTYPE AS "Work Type",
CASE
WHEN WO.REPORTDATE IS NULL
THEN TO_DATE('29-JAN-15 00:00:00', 'DD-MON-YY HH24:MI:SS')
ELSE WO.REPORTDATE
END AS "Reported Date",
WO.SITEID AS "Site",
CASE
WHEN WO.ACTFINISH IS NULL
THEN GREATEST(TRUNC(TO_DATE(SysDate, 'DD-MON-YY HH24:MI:SS') - TO_DATE(WO.REPORTDATE, 'DD-MON-YY HH24:MI:SS'), 6), 0)
WHEN WO.STATUS NOT IN ('COMP')
THEN GREATEST(TRUNC(TO_DATE(SysDate, 'DD-MON-YY HH24:MI:SS') - TO_DATE(WO.REPORTDATE, 'DD-MON-YY HH24:MI:SS'), 6), 0)
WHEN WO.STATUS IN ('COMP')
THEN GREATEST(TRUNC(TO_DATE(WO.ACTFINISH, 'DD-MON-YY HH24:MI:SS') - TO_DATE(WO.REPORTDATE, 'DD-MON-YY HH24:MI:SS'), 6), 0)
END AS "Age",
WO.EXT_DISTWORKTYPE,
LOCOFF.EXT_OFFICE,
CASE
WHEN LOCOFF.EXT_SRV_POLYGON IN ('BOF', 'CDA', 'COL', 'DAC', 'GOS', 'KEL', 'KLF', 'LAG', 'LEC', 'MED', 'PUM', 'RIT', 'ROS', 'SAN', 'SPO')
THEN 'GAS'
WHEN LOCOFF.EXT_SRV_POLYGON IN ('CDC', 'COC', 'DAV', 'DPC', 'GRC', 'KEC', 'LCC', 'OTC', 'PAC', 'SAC', 'SPC')
THEN 'ELECTRIC'
ELSE 'MISSING'
END AS TYPE,
LOCOFF.EXT_STATECODE,
WO.OWNERGROUP,
WO.EXT_JOBCODE
FROM LOCATIONS LOCOFF
RIGHT JOIN WORKORDER WO
ON WO.LOCATION = LOCOFF.LOCATION
WHERE WO.STATUS NOT IN ('CLOSE', 'WAIV', 'CAN', 'REJ', 'REVOKED')
AND LOCOFF.SITEID = 'OPS'
AND WO.EXT_JOBCODE NOT LIKE 'A%' AND WO.E`enter code here`XT_JOBCODE NOT LIKE 'B%'
AND WO.EXT_JOBCODE NOT IN ('K008','K009','I006','I007','I008');

You can nest case expressions if you only want to modify the existing column value (rather than adding a separate column with the 'wrong polygon' message):
CASE
WHEN LOCOFF.EXT_SRV_POLYGON IN ('BOF', 'CDA', 'COL', 'DAC', 'GOS', 'KEL', 'KLF', 'LAG', 'LEC', 'MED', 'PUM', 'RIT', 'ROS', 'SAN', 'SPO')
THEN
CASE
WHEN WO.EXT_DISTWORKTYPE IN ('EC', 'ES', 'ET')
THEN 'WRONG POLYGON'
ELSE 'GAS'
END
WHEN LOCOFF.EXT_SRV_POLYGON IN ('CDC', 'COC', 'DAV', 'DPC', 'GRC', 'KEC', 'LCC', 'OTC', 'PAC', 'SAC', 'SPC')
THEN
CASE
WHEN WO.EXT_DISTWORKTYPE IN ('GC', 'GT')
THEN 'WRONG POLYGON'
ELSE 'ELECTRIC'
END
ELSE 'MISSING'
END AS TYPE,
Quick SQL Fiddle demos with the same made-up data; your original case and this nested case, which gives:
EXT EX TYPE
--- -- -------------
BOF GC GAS
CDA GT GAS
SPO ES WRONG POLYGON
CDC EC ELECTRIC
COC ET ELECTRIC
SPC GC WRONG POLYGON
This is a bit simpler than trying to do a second step that interprets the TYPE value, because you can't refer to a column alias in the same level of query; you would need to make your existing query into an inline view.

Will an extra case not do it?
CASE
WHEN WO.EXT_DISTWORKTYPE IN ('GC', 'GT')
AND LOCOFF.EXT_SRV_POLYGON IN ('CDC', 'COC', 'DAV', 'DPC', 'GRC', 'KEC', 'LCC', 'OTC', 'PAC', 'SAC', 'SPC') --electronic
THEN 'WRONG POLYGON'
CASE
WHEN WO.EXT_DISTWORKTYPE IN ('EC', 'ES', 'ET' )
AND LOCOFF.EXT_SRV_POLYGON IN ('BOF', 'CDA', 'COL', 'DAC', 'GOS', 'KEL', 'KLF', 'LAG', 'LEC', 'MED', 'PUM', 'RIT', 'ROS', 'SAN', 'SPO') --gas
THEN 'WRONG POLYGON'
ELSE 'MSSING'
END AS YOURANSWER,
You could do an case within a case
CASE
WHEN (TRUE) THEN
CASE WHEN (true) THEN 'a' ELSE 'b' END
ELSE
'A'
END

Related

Snowflake Query/task gets canceled cause of timelimit

I set up a code, to load Data from Google Analytics from a raw GA table to an adapted table, that offers more insights.
Somehow the Task is not running inside the defined time limit of 3600 seconds.
So the task is getting canceled and no data is loaded.
"Statement reached its statement or warehouse timeout of 3,600 second(s) and was canceled."
Then I load it in a manual way by using a fixed Clause: WHERE gae."DAY"='2020-03-31' instead of
WHERE gae."DAY">=CuRRENT_DATE-1. It takes still much time but works in the end.
How can I make this query faster? Or anyway, solve my problem.
CREATE OR REPLACE TASK dm."Website"."x009_002_all_GA_events"
WAREHOUSE = marketing_wh
SCHEDULE = 'USING CRON 26 5 * * * Europe/Berlin'
AS
merge into DM."Website".ALL_GA_EVENTS_CLEAN target --DM."Website".ALL_GA_EVENTS target
using (
SELECT
GAEVENTACTION AS GAEVENTACTION,
GAEVENTCATEGORY AS GAEVENTCATEGORY,
"DAY" AS Datum,
DEVICE_TYPE AS Device,
EVENT_COUNT AS EventCount,
GAUNIQUEEVENTS AS Uniqueevents,
EVENT_VALUE AS eventvalue,
LABELS AS labelz,
URL AS urlz,
--split_part(LABELS,'/_',2) AS "HITSTAMP",
CASE WHEN split_part(LABELS,'/_',2) IS NOT NULL THEN TRY_CAST(split_part(LABELS,'/_',2) AS timestamp) ELSE NULL END AS "HITSTAMP",
split_part(LABELS,'/_',3) AS EVENT_INFO,
split_part(LABELS,'/_',1) AS "SESSIONID",
CASE
WHEN CONTAINS (URL, '/checkout/')=TRUE THEN split_part(URL,'/',3)
WHEN CONTAINS (URL, '/auto/')=TRUE THEN split_part(split_part(URL,'/',3),'?',1)
WHEN CONTAINS (URL, '/angebote/')=TRUE THEN split_part(URL,'/',3)
ELSE 'no vehicle'
END AS vehicleID,
rank() over (partition BY "SESSIONID" order by "HITSTAMP") as "RANK",
CASE
WHEN (GAEVENTACTION= ('pdp_flash_offer_request' )) THEN
CASE WHEN split_part(LABELS,'/_',2)=(SELECT min(split_part(t2.LABELS,'/_',2))
FROM "DL_Datatap"."PUBLIC"."GA_all_events" t2
WHERE split_part(t2.LABELS,'/_',1)=split_part(gae.LABELS,'/_',1) AND gae.GAEVENTACTION=t2.GAEVENTACTION)
THEN TRUE
ELSE FALSE
END
WHEN (GAEVENTACTION= ('chat_started')) THEN
CASE WHEN split_part(LABELS,'/_',2)=(SELECT min(split_part(t2.LABELS,'/_',2))
FROM "DL_Datatap"."PUBLIC"."GA_all_events" t2
WHERE split_part(t2.LABELS,'/_',1)=split_part(gae.LABELS,'/_',1) AND gae.GAEVENTACTION=t2.GAEVENTACTION)
THEN TRUE
ELSE FALSE
END
WHEN (GAEVENTACTION= ('Direct_checkout_send')) THEN
CASE WHEN split_part(LABELS,'/_',2)=(SELECT min(split_part(t2.LABELS,'/_',2))
FROM "DL_Datatap"."PUBLIC"."GA_all_events" t2
WHERE split_part(t2.LABELS,'/_',1)=split_part(gae.LABELS,'/_',1) AND gae.GAEVENTACTION=t2.GAEVENTACTION)
THEN TRUE
ELSE FALSE
END
WHEN (GAEVENTACTION= ('pdp_offer_request')) THEN
CASE WHEN split_part(LABELS,'/_',2)=(SELECT min(split_part(t2.LABELS,'/_',2))
FROM "DL_Datatap"."PUBLIC"."GA_all_events" t2
WHERE split_part(t2.LABELS,'/_',1)=split_part(gae.LABELS,'/_',1) AND gae.GAEVENTACTION=t2.GAEVENTACTION)
THEN TRUE
ELSE FALSE
END
WHEN (GAEVENTACTION= ('agent-requested')) THEN
CASE WHEN split_part(LABELS,'/_',2)=(SELECT min(split_part(t2.LABELS,'/_',2))
FROM "DL_Datatap"."PUBLIC"."GA_all_events" t2
WHERE split_part(t2.LABELS,'/_',1)=split_part(gae.LABELS,'/_',1) AND gae.GAEVENTACTION=t2.GAEVENTACTION)
THEN TRUE
ELSE FALSE
END
WHEN (GAEVENTACTION= ('SERP_softlead_send')) THEN
CASE WHEN split_part(LABELS,'/_',2)=(SELECT min(split_part(t2.LABELS,'/_',2))
FROM "DL_Datatap"."PUBLIC"."GA_all_events" t2
WHERE split_part(t2.LABELS,'/_',1)=split_part(gae.LABELS,'/_',1) AND gae.GAEVENTACTION=t2.GAEVENTACTION)
THEN TRUE
ELSE FALSE
END
ELSE False
END AS "GOAL_EVENT"
FROM "DL_Datatap"."PUBLIC"."GA_all_events" gae
---WHERE gae."DAY"='2020-03-31'
WHERE gae."DAY">=CuRRENT_DATE-1
) SOURCE
ON target.SESSIONID=SOURCE."SESSIONID" AND target.HITSTAMP=SOURCE."HITSTAMP" AND target.EVENT_ACTION=SOURCE.GAEVENTACTION AND target."Date"=SOURCE.Datum
when NOT matched then INSERT (EVENT_ACTION, EVENT_CATEGORY, "Date", DEVICE, TOTAL_EVENTS, UNIQUE_EVENTS, EVENT_VALUE, EVENT_LABEL, URL, HITSTAMP, EVENT_INFO, SESSIONID, VEHICLEID, EVENT_SEQUENCE, GOAL_EVENT)
VALUES (SOURCE.GAEVENTACTION, SOURCE.GAEVENTCATEGORY, SOURCE.Datum, SOURCE.Device, SOURCE.eventcount, SOURCE.Uniqueevents, SOURCE. eventvalue, SOURCE.labelz, SOURCE.urlz, SOURCE."HITSTAMP", SOURCE.EVENT_INFO, SOURCE."SESSIONID", SOURCE.vehicleid, SOURCE."RANK", SOURCE."GOAL_EVENT"
)
You can increase the task timeout limit as a workaround:
CREATE OR REPLACE TASK dm."Website"."x009_002_all_GA_events"
WAREHOUSE = marketing_wh
SCHEDULE = 'USING CRON 26 5 * * * Europe/Berlin'
USER_TASK_TIMEOUT_MS = 86400000
AS
...
https://docs.snowflake.com/en/sql-reference/sql/create-task.html#optional-parameters
If you need help to tune your SQL, please submit a case to support. As they can see metadata of your tables, and execution plans of your previous runs, they can guide you to tune the query, cluster your target table etc..

Basic ways to optimize this query?

title pretty much says it all. I wrote this big, ugly query that works...however it takes forever to run. I have no experience whatsoever with optimizing SQL, and am pretty new to the language and its functions. I realize none of you will be familiar with the environment I am working in, but I was just wondering if any basic things jump out at you about it. Thanks!
SELECT MAX(INVOICE.invoice_id) invoice_id, MAX(invoice.vendor_num) vendor_num, max(invoice.vendor_name) vendor_name,
MAX(invoice.po_number) po_number, MAX(invoice.invoice_date) invoice_date, MAX(invoice.invoice_num) invoice_num,
MAX(invoice.terms_name) terms_name, MAX(invoice.invoice_amount) invoice_amount, MAX(invoice.amount_applicable_to_discount) amount_applicable_to_discount,
MAX(invoice.amount_paid) amount_paid, MAX(invoice.payment_date) payment_date, MAX(invoice.document_id) document_id,
MAX(invoice.filename) filename,
STAMPS.page_markups_view_id, STAMPS.TEXT, STAMPS.TOOL_NAME
FROM
(SELECT DISTINCT inv.invoice_id,
vendor.segment1 vendor_num,
vendor.vendor_name,
MAX(poh.segment1) po_number,
inv.invoice_date,
inv.invoice_num,
terms.name terms_name,
inv.invoice_amount,
inv.amount_applicable_to_discount,
inv.amount_paid,
pmt.check_date payment_date,
path.document_id,
vendor.segment1 || '-' || inv.invoice_num || '.pdf' filename
FROM apps.ap_invoices_all inv,
apps.ap_invoice_distributions_all dist,
apps.po_distributions_all podi,
apps.ap_invoice_payment_history_v pmt,
apps.fnd_attached_docs_form_vl fnd,
markview.mv_page_image_paths path,
apps.po_vendors vendor,
apps.po_headers_all poh,
apps.ap_terms terms
WHERE inv.invoice_id = to_number(fnd.pk1_value)
AND inv.invoice_id = dist.invoice_id
AND poh.po_header_id(+) = podi.po_header_id
AND podi.po_distribution_id(+) = dist.po_distribution_id
AND fnd.file_name = to_char(path.document_id)
AND inv.invoice_id = pmt.invoice_id
AND fnd.category_description = 'MarkView Document'
AND fnd.entity_name = 'AP_INVOICES'
AND inv.vendor_id = poh.vendor_id(+)
AND inv.terms_id = terms.term_id
AND inv.vendor_id = vendor.vendor_id
AND path.platform_name = 'UNIX_FS_TO_DOC_SERVER'
AND pmt.void = 'N'
and inv.invoice_id = 1908784
GROUP BY
inv.invoice_id,
vendor.segment1 ,
vendor.vendor_name,
inv.invoice_date,
inv.invoice_num,
terms.name ,
inv.invoice_amount,
inv.amount_applicable_to_discount,
inv.amount_paid,
path.document_id,
pmt.check_date,
vendor.segment1 || '-' || inv.invoice_num || '.pdf'
) INVOICE,
( SELECT mp.document_id,
moi.markup_object_id,
moi.page_markups_view_id,
moi.text,
mvt.tool_name,
mp.page_id
FROM markview.mv_markup_object moi,
markview.mv_tool mvt,
markview.mv_page_markups_view mpmv,
markview.mv_page mp
WHERE moi.tool_id = mvt.tool_id
AND mp.page_id = mpmv.page_id
AND mpmv.page_markups_view_id = moi.page_markups_view_id
AND mvt.tool_id IN
(
SELECT mvt.tool_id
FROM markview.mv_tool
WHERE mvt.tool_name IN ( 'Green Text',
'Blue Sticky Note' ) )) STAMPS
WHERE invoice.document_id = stamps.document_id(+)
GROUP BY
page_markups_view_id, TEXT, TOOL_NAME
)

Oracle case when, else, then error - missing keyword

The table I'm working with has these weird coded times, I'm trying to format them. The error I'm getting is "Missing Keyword". TRANS_NUMBER is a string of numbers that I need reformat.
CASE POST_TIME.TRANS_NUMBER
WHEN '' THEN ''
WHEN NULL THEN ''
WHEN SUBSTR(POST_TIME.TRANS_NUMBER,10,1) =':' THEN CONCAT('0', SUBSTR(POST_TIME.TRANS_NUMBER,9,1))
ELSE SUBSTR(POST_TIME.TRANS_NUMBER,9,2)
END AS "POSTED_HOUR",
CASE POST_TIME.TRANS_NUMBER
WHEN '' THEN ''
WHEN NULL THEN ''
WHEN SUBSTR(POST_TIME.TRANS_NUMBER,12,1) =':' THEN CONCAT( CONCAT( '0', SUBSTR(POST_TIME.TRANS_NUMBER,11,1) ), CONCAT(' ', SUBSTR(POST_TIME.TRANS_NUMBER,13,2) ) )
ELSE CONCAT( CONCAT( '0', SUBSTR(POST_TIME.TRANS_NUMBER,11,2) ), CONCAT(' ', SUBSTR(POST_TIME.TRANS_NUMBER,13,2) ) )
END AS "POSTED_MINUTE"
You're mixing up the syntax for simple and searched CASE statements which is why you're getting the error.
You can rewrite this as:
CASE WHEN POST_TIME.TRANS_NUMBER IS NULL THEN NULL
WHEN SUBSTR(POST_TIME.TRANS_NUMBER,10,1) = ':' THEN '0'||SUBSTR(POST_TIME.TRANS_NUMBER,9,1)
ELSE SUBSTR(POST_TIME.TRANS_NUMBER,9,2)
END AS "POSTED_HOUR",
CASE WHEN POST_TIME.TRANS_NUMBER IS NULL THEN NULL
WHEN SUBSTR(POST_TIME.TRANS_NUMBER,12,1) =':' THEN '0'||SUBSTR(POST_TIME.TRANS_NUMBER,11,1)||' '||SUBSTR(POST_TIME.TRANS_NUMBER,13,2)
ELSE '0'||SUBSTR(POST_TIME.TRANS_NUMBER,11,2)||' '||SUBSTR(POST_TIME.TRANS_NUMBER,13,2)
END AS "POSTED_MINUTE"
N.B. I've replaced each of your CONCAT()s with the more common and (IMHO) easily read ||
Plus the above is untested, since you didn't provide any example data for us to test with.
ETA: You don't even need to explicitly handle the case when POST_TIME.TRANS_NUMBER is null, as SUBSTR() of a null value returns null.
Your 3rd when should be nested case:
CASE POST_TIME.TRANS_NUMBER
WHEN '' THEN ''
WHEN NULL THEN ''
else
case WHEN SUBSTR(POST_TIME.TRANS_NUMBER,10,1) =':' THEN CONCAT('0', SUBSTR(POST_TIME.TRANS_NUMBER,9,1))
ELSE SUBSTR(POST_TIME.TRANS_NUMBER,9,2)
end
END AS "POSTED_HOUR",

How can I convert Oracle round statement to SQL server syntax?

How can I convert:
round(DECODE(PC_TTL.WAGETYPE, 3085, PC_TTL.WORKHOURS, DECODE(PC_TTL.UNIT, '010', PC_TTL.WORKHOURS/8, PC_TTL.WORKHOURS)) , 2)
to SQL server syntax?
Unless I misunderstood the DECODE logic, this should do the trick:
ROUND(
CASE WHEN PC_TTL.WAGETYPE = 3085 THEN PC_TTL.WORKHOURS
ELSE
CASE WHEN PC_TTL.UNIT = '010' THEN PC_TTL.WORKHOURS/8
ELSE PC_TTL.WORKHOURS
END
END, 2)
This will work in SQL Server and Oracle.
You can do it using a simple case statement.
ROUND (
CASE
WHEN PC_TTL.WAGETYPE = 3085 THEN PC_TTL.WORKHOURS
WHEN PC_TTL.UNIT = '010' THEN PC_TTL.WORKHOURS / 8
ELSE PC_TTL.WORKHOURS
END, 2 )

Suppress ORA-01403: no data found excpetion

I have the following code
SELECT SUM(nvl(book_value,
0))
INTO v_balance
FROM account_details
WHERE currency = 'UGX';
--Write the balance away
SELECT SUM(nvl(book_value,
0))
INTO v_balance
FROM account_details
WHERE currency = 'USD';
--Write the balance away
Now the problem is, there might not be data in the table for that specific currency, but there might be data for the 'USD' currency. So basically I want to select the sum into my variable and if there is no data I want my stored proc to continue and not throw the 01403 exception.
I don't want to put every select into statement in a BEGIN EXCEPTION END block either, so is there some way I can suppress the exception and just leave the v_balance variable in an undefined (NULL) state without the need for exception blocks?
select nvl(balance,0)
into v_balance
from
(
select sum(nvl(book_value,0)) as balance
from account_details
where currency = 'UGX'
);
SELECT L1.PKCODE L1CD, L1.NAME L1N, L1.LVL L1LVL,
L2.PKCODE L2CD, L2.NAME L2N, L2.LVL L2LVL,
L5.PKCODE L5CD, L5.NAME L5N,
INFOTBLM.OPBAL ( L5.PKCODE, :PSTDT, :PSTUC, :PENUC, :PSTVT, :PENVT ) OPBAL,
INFOTBLM.DEBIT ( L5.PKCODE, :PSTDT,:PENDT, :PSTUC, :PENUC, :PSTVT, :PENVT ) AMNTDR,
INFOTBLM.CREDIT ( L5.PKCODE, :PSTDT,:PENDT, :PSTUC, :PENUC, :PSTVT, :PENVT ) AMNTCR
FROM FSLVL L1, FSLVL L2, FSMAST L5
WHERE L2.FKCODE = L1.PKCODE
AND L5.FKCODE = L2.PKCODE
AND L5.PKCODE Between :PSTCD AND NVL(:PENCD,:PSTCD)
GROUP BY L1.PKCODE , L1.NAME , L1.LVL ,
L2.PKCODE , L2.NAME , L2.LVL ,
L5.PKCODE , L5.NAME
ORDER BY L1.PKCODE, L2.PKCODE, L5.PKCODE

Resources