CASE WHEN THEN resolving to zeros in SQLite - sqlite

I am using SQLite inside my .NET application and I have the following query:
select (CASE IFNULL(CCODE_1, '') when 'STD' then '_' else '' end) +
(CASE IFNULL(CFRRR_CS, '') when '1' then 'F_' when '2' then 'R_' when '3' then 'FR_' else '' end) +
IFNULL(CCODE_1, '') +
(CASE when (IFNULL(CCODE_2, '') = '') then '' else '_' end) +
IFNULL(CCODE_2, '') +
(CASE when (IFNULL(CCODE_3, '') = '') then '' else '_' end) +
IFNULL(CCODE_3, '') as OptionID
from X20_TIRES
The query above produces a single OptionID column of all 0s. Nothing else.
And here is some sample data from X20_TIRES:
I am expecting results such as the following:
R_F41A
R_F41V
etc...
It's clear to me that the case/when/then is breaking down and simply spitting out 0s, but I cannot understand why. What am I doing wrong?

If you want to concatenate all these results from the CASE statements,
you must use the || operator instead of +:
select
(CASE IFNULL(CCODE_1, '') when 'STD' then '_' else '' end) ||
(CASE IFNULL(CFRRR_CS, '') when '1' then 'F_' when '2' then 'R_' when '3' then 'FR_' else '' end) ||
IFNULL(CCODE_1, '') ||
(CASE when (IFNULL(CCODE_2, '') = '') then '' else '_' end) ||
IFNULL(CCODE_2, '') ||
(CASE when (IFNULL(CCODE_3, '') = '') then '' else '_' end) ||
IFNULL(CCODE_3, '') as OptionID
from X20_TIRES

Related

Invalid Time Literal in Teradata Dynamic SQL

The following stored procedure works fine when I use static sql to insert values into the DBCMNGR.ALERTREQUEST but does not work when trying to use the dynamic sql string.
I get invalid date literal and time literal when trying to call the below stored procedure.
CALL TESTDB.ALERT_REQUEST_INSERT('Test_JobName','Test_JobDescription',
'Test_ActionDestination','Test_JobFullMessage')
Need help to actually work this without any errors.
In the DBCMNGR.ALERTREQUEST the DATE and time are defined as follows:
ReqDate DATE FORMAT 'YYYY/MM/DD'
ReqTime INTEGER
REPLACE PROCEDURE TESTDB.ALERT_REQUEST_INSERT( IN p_JobName CHARACTER(60), IN p_JobDescription CHARACTER(120), IN p_ActionDestination CHARACTER(120), IN p_JobFullMessage CHARACTER(600) ) )
BEGIN
SET SQLSTR = 'INSERT INTO DBCMNGR.ALERTREQUEST ' || '(AlertRequest.ReqDate ' || ',AlertRequest.ReqTime ' || ',AlertRequest.JobName ' || ',AlertRequest.Description ' || ',AlertRequest.EventValue ' || ',AlertRequest.ActionCode ' || ',AlertRequest.RepeatPeriod ' || ',AlertRequest.Destination ' || ',AlertRequest.Message ' || ') ' || 'VALUES ( ' || ' DATE ' || ',TIME ' || ''',''' || TRIM(p_JobName) || ''',''' || TRIM(p_JobDescription) || ''',0 ' || ',''+'' ' || ',0 ' || ''',''' || TRIM(p_ActionDestination) || ',''' || TRIM(p_JobFullMessage) || ''');';
EXECUTE IMMEDIATE SQLSTR; END;

PL/SQL VARCHAR2 Max Length

I can't seem to use a VARCHAR2 of more than 4000 chars in 11G, but I see that I should be able to get to 32776.
PROCEDURE prcName
(piCoSite IN CHAR
,piRaciId IN NUMBER
,piDept IN VARCHAR2
,poRecordset OUT SYS_REFCURSOR) AS
locSql1 VARCHAR2(32000 CHAR);
BEGIN
locSql1 :=
'SELECT' ||
' H.TABLE_HEAD_ID ' ||
' ,H.TABLE_HEAD_DEPT ' ||
' ,H.TABLE_HEAD_DESCRIPTION ' ||
' ,H.TABLE_HEAD_STATUS ' ||
' ,H.TABLE_HEAD_SCOPE ' ||
' ,H.TABLE_HEAD_ORIGINATOR ' ||
' ,H.TABLE_HEAD_SUB_CATEGORY ' ||
' ,H.TABLE_HEAD_HIGH_RISK ' ||
' ,TRIM(C0.CNTCT_FIRSTNAME) || '' '' || TRIM(C0.CNTCT_SURNAME) wsRaisedBy ' ||
' ,(SELECT COUNT(*) FROM TABLE_EMPLOYEES E WHERE E.TABLE_EMPS_CO_SITE = H.TABLE_HEAD_CO_SITE AND E.TABLE_EMPS_ID = H.TABLE_HEAD_ID) wsNoEmployees ' ||
' ,(SELECT COUNT(*) FROM TABLE_TASKS T WHERE T.TABLE_TASK_CO_SITE = H.TABLE_HEAD_CO_SITE AND T.TABLE_TASK_ID = H.TABLE_HEAD_ID) wsNoActions ' ||
' FROM TABLE_HEADER H ' ||
' LEFT JOIN CONTACTS C0 ' ||
' ON C0.CNTCT_CO_SITE = H.TABLE_HEAD_CO_SITE ' ||
' AND C0.CNTCT_CODE = H.TABLE_HEAD_ORIGINATOR ' ||
' WHERE H.TABLE_HEAD_CO_SITE = ''' || piCoSite || '''' ||
' AND (H.TABLE_HEAD_ID = ''' || piRaciId || '''' || ' OR ''' || piRaciId || ''' = 0) ' ||
' AND (H.TABLE_HEAD_DEPT IN (''' || piDept || ''' ) OR ''' || piDept || ''' IS NULL ) ' ||
' AND (H.TABLE_HEAD_ORIGINATOR IN (' || piUser || ' ) OR ''' || piUser || ''' IS NULL ) ' ||
' AND (H.TABLE_HEAD_STATUS IN (' || piStatus || ' ) OR ''' || piStatus || ''' IS NULL ) ' ||
' ORDER BY TABLE_HEAD_ID ';
dbms_output.put_line(locSql1);
OPEN poRecordset FOR locSql1;
When I copy/paste the locSql1 variable it's nowhere near 32000 chars, but it's getting truncated.
Is there something within the Database to change or am I missing something?
Thanks.

Tuning Oracle SQL having NOT EXIST clause

I want to tune below query eliminating NOT EXIST clause specified in it. Can you please help.
GLT_temp_upload is temporary table where as DA_DUEDATE is partitioned table having huge data in it.
Please help
SELECT DISTINCT
batchid,
store_area,
STORE_AREA
|| ','
|| STORE_ID
|| ','
|| SMS_ID
|| ','
|| SMS_SERVICE
|| ','
|| SYNERGY_MODE_ID
|| ','
|| FREQUENCY
|| ','
|| DUEDATE
|| ','
|| STUDY_ID
|| ','
|| YEAR
|| ''
|| WEEK_ID
||',Not exist in Da_Duedate'
FROM GLT_temp_upload upload
WHERE upload.batchid = 1
AND NOT EXISTS
(SELECT due.week_id,
due.country_id,
due.year,
due.study_id,
due.store_id,
due.store_area,
due.synergy_mode_id,
upload.batchid,
due.due_date,
upload.sms_service
FROM DA_DUEDATE due
WHERE due.store_id = upload.store_id
AND due.study_id = upload.study_id
AND due.store_area = upload.store_area
AND due.frequency = upload.frequency
AND due.sms_service = upload.sms_service
AND due.week_id = upload.week_id
AND due.country_id = upload.country_id
AND due.year = upload.year
AND due.sms_id = upload.sms_id
AND due.synergy_mode_id =
upload.synergy_mode_id)
You may try NOT EXISTS / LEFT JOIN / NOT IN
In your NOT EXISTS it's enough to SELECT 1 instead of the list of columns
Sometimes LEFT JOIN can be more beneficial (depending on indexes, the size of the tables etc)
SELECT DISTINCT
batchid,
store_area,
STORE_AREA
|| ','
|| STORE_ID
|| ','
|| SMS_ID
|| ','
|| SMS_SERVICE
|| ','
|| SYNERGY_MODE_ID
|| ','
|| FREQUENCY
|| ','
|| DUEDATE
|| ','
|| STUDY_ID
|| ','
|| YEAR
|| ''
|| WEEK_ID
||',Not exist in Da_Duedate'
FROM GLT_temp_upload upload left join DA_DUEDATE due
ON due.store_id = upload.store_id
AND due.study_id = upload.study_id
AND due.store_area = upload.store_area
AND due.frequency = upload.frequency
AND due.sms_service = upload.sms_service
AND due.week_id = upload.week_id
AND due.country_id = upload.country_id
AND due.year = upload.year
AND due.sms_id = upload.sms_id
AND due.synergy_mode_id = upload.synergy_mode_id
WHERE upload.batchid = 1 and due.store_id is NULL;
I'd recommend you looking at the execution plan to find an optimal solution for your case.

How to group substrings in Teradata 14?

I have the following table in Teradata 14 , I am not allowed to write procedures and functions myself, but i can use strtok, strtok_split_to_table etc
id property
1 1234X (Yel), 2225Y (Red), 1234X (Gre),
2
3 1222Y (Pin),
4 1134E (Yel), 4565Y (Whi), 1134E (Red), 2222Y (Red),
How can I group the above table so that each object would have all attributes listed in one brackets
id property
1 1234X (Yel Gre), 2225Y (Red),
2
3 1222Y (Pin ),
4 1134E (Yel Red), 4565Y (Whi), 2222Y (Red),
The property code is always a 5 character string, e.g. 1222Y . The color code is always 3 character , e.g. Pin
I tried using this solution but got an error A column or character expression is larger than max size
In addition I tried strtok_split_to_table and was able to create a modified table, but do not how to proceed from that
Why do you store denormalized data in a RDBMS and then process it to create even worse denormalized output?
Modifying my solution from the link you posted to utilize STRTOK_SPLIT_TO_TABLE instead of recursion:
SELECT
id,
MAX(CASE WHEN newpos = 1 AND newgrp <> '(),' THEN newgrp ELSE '' END) ||
MAX(CASE WHEN newpos = 2 THEN newgrp ELSE '' END) ||
MAX(CASE WHEN newpos = 3 THEN newgrp ELSE '' END) ||
MAX(CASE WHEN newpos = 4 THEN newgrp ELSE '' END) ||
MAX(CASE WHEN newpos = 5 THEN newgrp ELSE '' END) ||
MAX(CASE WHEN newpos = 6 THEN newgrp ELSE '' END)
-- add as many CASEs as needed
FROM
(
SELECT
id,
ROW_NUMBER()
OVER (PARTITION BY id
ORDER BY newgrp) AS newpos,
TRIM(a || ' (' ||
MAX(CASE WHEN tokennum = 1 THEN b || ' ' ELSE '' END) ||
MAX(CASE WHEN tokennum = 2 THEN b || ' ' ELSE '' END) ||
MAX(CASE WHEN tokennum = 3 THEN b || ' ' ELSE '' END) ||
MAX(CASE WHEN tokennum = 4 THEN b || ' ' ELSE '' END) ||
MAX(CASE WHEN tokennum = 5 THEN b || ' ' ELSE '' END) ||
MAX(CASE WHEN tokennum = 6 THEN b || ' ' ELSE '' END)
-- add as many CASEs as needd
) || '), ' AS newgrp
FROM
(
SELECT
id, tokennum,
TRIM(SUBSTRING(token FROM 1 FOR POSITION('(' IN TRIM(token)||'(') - 1)) AS a,
TRIM(TRAILING ')' FROM SUBSTRING(token FROM POSITION('(' IN token) + 1)) AS b
FROM
TABLE( STRTOK_SPLIT_TO_TABLE(vt.id, vt.property, ',')
RETURNS (id INT,
tokennum INT,
token VARCHAR(30) CHARACTER SET UNICODE
)
) AS dt
) AS dt
GROUP BY id, a
) AS dt
GROUP BY id;
If you got access to the TDStats.udfconcat function it can be further simplified (but there's way to control the order of properties:
SELECT id,
CASE
WHEN TRIM(TDStats.udfconcat(' ' || a || ' ' || b)) || ',' <> '(),'
THEN TRIM(TDStats.udfconcat(' ' || a || ' ' || b)) || ','
ELSE ''
END
FROM
(
SELECT
id,
TRIM(SUBSTRING(token FROM 1 FOR POSITION('(' IN TRIM(token)||'(') - 1)) AS a,
'('|| OTRANSLATE(TDStats.udfconcat(TRIM(TRAILING ')' FROM SUBSTRING(token FROM POSITION('(' IN token) + 1))), ',', ' ') || ')'AS b
FROM
TABLE( STRTOK_SPLIT_TO_TABLE(vt.id, vt.property, ',')
RETURNS (id INT,
tokennum INT,
token VARCHAR(30) CHARACTER SET UNICODE
)
) AS dt
GROUP BY id, a
) AS dt
GROUP BY id;
Most of the work was fiddling with the spaces and commas in the right place to get the requested output.
Still i would never store data as such in a RDBMS.
Try this , I had slightly modified dnoeths query from your post
WITH RECURSIVE cte
(id,
len,
remaining,
word,
pos
) AS (
SELECT
id,
POSITION(',' IN property || ',') - 1 AS len,
SUBSTRING(property || ',' FROM len + 2) AS remaining,
TRIM(SUBSTRING(property FROM 1 FOR len)) AS word,
1
FROM TableA
UNION ALL
SELECT
id,
POSITION(',' IN remaining)- 1 AS len_new,
SUBSTRING(remaining FROM len_new + 2),
TRIM(SUBSTRING(remaining FROM 1 FOR len_new)),
pos + 1
FROM cte
WHERE remaining <> ''
)
SELECT
id,
MAX(CASE WHEN newpos = 1 THEN newgrp ELSE '' END) ||
MAX(CASE WHEN newpos = 2 THEN newgrp ELSE '' END) ||
MAX(CASE WHEN newpos = 3 THEN newgrp ELSE '' END) ||
MAX(CASE WHEN newpos = 4 THEN newgrp ELSE '' END) ||
MAX(CASE WHEN newpos = 5 THEN newgrp ELSE '' END) ||
MAX(CASE WHEN newpos = 6 THEN newgrp ELSE '' END)
-- add as many CASEs as needed
FROM
(
SELECT
id,
ROW_NUMBER()
OVER (PARTITION BY id
ORDER BY newgrp) AS newpos,
a ||
MAX(CASE WHEN pos = 1 THEN '(' || b ELSE '' END) ||
MAX(CASE WHEN pos = 2 THEN ' ' || b ELSE '' END) ||
MAX(CASE WHEN pos = 3 THEN ' ' || b ELSE '' END) ||
MAX(CASE WHEN pos = 4 THEN ' ' || b ELSE '' END) ||
MAX(CASE WHEN pos = 5 THEN ' ' || b ELSE '' END) ||
MAX(CASE WHEN pos = 6 THEN ' ' || b ELSE '' END)
-- add as many CASEs as needed
|| '), ' AS newgrp
FROM
(
SELECT
id,
ROW_NUMBER()
OVER (PARTITION BY id, a
ORDER BY pos) AS pos,
SUBSTRING(word FROM 1 FOR POSITION('(' IN word) - 1) AS a,
TRIM(TRAILING ')' FROM SUBSTRING(word FROM POSITION('(' IN word) + 1)) AS b
FROM cte
WHERE word <> ''
) AS dt
GROUP BY id, a
) AS dt
GROUP BY id
UNION ALL
SELECT id,property FROM TableA WHERE property IS NULL OR TRIM(property)=' ';

How can i add extra columns to my select statement using with clause

How can add V_SP_CDRA_WEEKLY_UPDATE.indication column to following sql statement. As of now it is displaying only str_out column. any help will be appreciated.
with
transformation(str_in,flag,str_out) as
(select substr(s,instr(s,'href=') + 5),1,cast(substr(s,1,instr(s,'href=') + 4) as varchar2(4000))
from (select KEY_DOCUMENTS s From V_SP_CDRA_WEEKLY_UPDATE Where KEY_DOCUMENTS like '%%https:%%')
union all
select substr(str_in,2),
case when flag = 1
and substr(str_in,1,1) != '>'
then 1
when substr(str_in,1,1) = '>'
then 0
when substr(str_in,1,5) = 'href='
then 1
else 0
end,
str_out || case when substr(str_in,1,1) = ' '
and flag = 1
then '%20'
else substr(str_in,1,1)
end
from transformation
where length(str_in) > 0
)
select str_out
from transformation
where str_in is null;
I don't know your data, so I try to ask your question:
with
transformation(str_in, flag, str_out, indication) as
(select substr(s,instr(s,'href=') + 5),
1,
cast(substr(s,1,instr(s,'href=') + 4) as varchar2(4000)),
i
from (select KEY_DOCUMENTS s, indication i
From V_SP_CDRA_WEEKLY_UPDATE
Where KEY_DOCUMENTS like '%%https:%%')
union all
select substr(str_in,2),
case when flag = 1 and substr(str_in,1,1) != '>'
then 1
when substr(str_in,1,1) = '>'
then 0
when substr(str_in,1,5) = 'href='
then 1
else 0
end,
str_out || case when substr(str_in,1,1) = ' ' and flag = 1
then '%20'
else substr(str_in,1,1)
end,
null as i
from transformation
where length(str_in) > 0)
select str_out, indication
from transformation
where str_in is null;

Resources