Is it possible to build sql parts within a case
For example I have a database where I have a statement
where p.budget_key = l.Budget_key
and p.amount_finished > 0
and p.amount_finished > (select isnull(sum(dline_amount),0) from trimergo.delivery_line where dline_planningid = p.planning_key)
now what i want is like an if statement
AND CASE WHEN p.type_name = 'Service' THEN and p.amount_finished > 0
ELSE p.amount_finished < 0
Or something along these lines. Building actually sql segments
Is this possible?
This is for MS Server 2012 version.
after first awnser. my currect syntax is
AND (CASE WHEN p.type_name <> 'Service' THEN p.amount_finished END ) > 0
AND (CASE WHEN p.type_name <> 'Service' THEN p.amount_finished END ) > (select isnull(sum(dline_amount),0) from trimergo.delivery_line where dline_planningid = p.planning_key)
AND (CASE WHEN p.type_name = 'Service' THEN p.status END ) > '150-01'
the point now remains. that if the type_name = 'Service' then it only needs to check the p.status part and now the amount parts. so is it possible to like "choose" which AND statement he needs to use for this query?
Case is possible in Where clause.Syntax of Case is wrong in your example,
AND (CASE WHEN p.type_name = 'Service' THEN p.amount_finished
ELSE 0 End) = #someVariable
Related
*where (citiStatus NOT IN ('Paid Off' ,'PAID-O'))
and (
revolver = 0
and (
(commitmentDate = '')
or (
(commitmentDate != '')
and (#currentDate < DATEADD(day, #noofDays, commitmentDate))
)
)
) // until here should verify with where condition . even if it is failed or not should execute next statement .
and (citiStatus NOT IN ('CANCELLED','Cancelled/Dead') or #currentMonth = MONTH(statusModifiedDate))-- this is will if above AND condition fails even if its true(but this should execute even to filter data).*
You need to have in mind two simple rules, the Associativity of Logical Operators is always from left to right, and the correct use of Parentheses having in consideration the logic of your problem for example:
select case when 1=1 and 1=2 or 3=3 then 1 else 0 end as result from dual;--result 1
First we evaluate 3=3 TRUE -> 1=2 FALSE -> evaluate OR OPERATOR (TRUE OR FALSE)-> TRUE
Second 1=1 TRUE -> evaluate AND OPERATOR -> TRUE AND TRUE -> TRUE
IF TRUE THEN 1
My advice is always to use Parentheses, in this way you will evaluate the whole expression and no token by token for example
select case when ((1=1 and 2=2) or 3=3) and 5=6 then 1 else 0 end as result from dual; --0
select case when (1=1 and 2=2) or (3=3 and 5=6) then 1 else 0 end as result from dual; --1
When you are loading a teradata table in bteq you can set the queryband for block level compression. This even works when you are using querygrid and inserting from a foreign server.
SET QUERY_BAND = 'BlockCompression=Yes;' UPDATE FOR SESSION;
My issue is that I am creating a table on an Aster system and then using the load to teradata function. I suspect there is a syntax call where I can set the query band as part of the load_to_teradata call but after searching the internet and through a reem of teradata documentation I haven't found anything yet.
-- Load Agg data for the YYYYMM to Teradta
SELECT SUM(loaded_row_count),SUM(error_row_count)
FROM load_to_teradata (
ON ( select
Cust_id
, cast(lst_cnf_actvy_dt_tm as date) as lst_cnf_actvy_dt
, cast(sum(str_cnt ) as INTEGER) as acct_open_brnch_use_cnt
, cast(sum(phone_cnt ) as INTEGER) as acct_open_phn_use_cnt
, cast(sum(mail_cnt ) as INTEGER) as acct_open_mail_use_cnt
, cast(sum(onlnchnl_cnt) as INTEGER) as acct_open_onln_use_cnt
, cast(sum(mblbnk_cnt ) as INTEGER) as acct_open_mbl_dvc_use_cnt
, cast(sum(acctopen_cnt) as INTEGER) as acct_open_trck_chnl_cnt
from <someDB>.<someTBL>
where acctopen_cnt > 0
and lower(lst_cnf_actvy_typ_cd) = 'acctopen'
and cast(lst_cnf_actvy_dt_tm as date) between
cast(substring('${YYYYMM}' from 1 for 4) || '-' || substring('${YYYYMM}' from 5 for 2) || '-01' as date) and
cast((cast(substring('${YYYYMM}' from 1 for 4) || '-' || substring('${YYYYMM}' from 5 for 2) || '-01' as date) + interval '1 month') - interval '1 day' as date)
and (str_cnt > 0 or phone_cnt > 0 or mail_cnt > 0 or onlnchnl_cnt > 0 or mblbnk_cnt > 0)
group by 1,2 )
TDPID('TD_RDBMS_C2T') USERNAME('${c2tUID}') PASSWORD('${c2tPWD}') ${LDAP_IND_AST_C2T}
TARGET_TABLE ( 'C2T.t_yyyymm_agg' ) LOG_TABLE ('C2T.t_yyyymm_aggLOG')
MAX_SESSIONS(120));
Was able to get the syntax for the load_to_teradata options. You can see the query_band_sess_info argument after max_sessions and before query_timeout...
load_to_teradata(
ON (source query)
TDPID('tdpid')
TARGET_TABLE('fully-qualified table name')
[ERROR_TABLES('error table'[, 'unique constraint violation table'])]
[LOG_TABLE('table name')]
Teradata QueryGrid: Aster-Teradata Connector
Loading Data From Aster Database to Teradata
Aster Database User Guide for Aster Appliances 301
[USERNAME('username')]
[PASSWORD('password')]
[LOGON_MECHANISM('TD2' | 'LDAP' | 'KRB5')]
[LOGON_DATA('mechanism-specific logon data')]
[ACCOUNT_ID('account-id')]
[TRACE_LEVEL('trace-level')]
[NUM_INSTANCES('instance-count')]
[START_INSTANCE('start-instance')]
[MAX_SESSIONS('max-sessions-number')]
[QUERY_BAND_SESS_INFO('key1=value1;key2=value2;...')]
[QUERY_TIMEOUT('timeout-in-seconds')]
[AUTO_TUNE_INSTANCES('yes'|'no')]
[WORKINGDATABASE(‘dbname’)]
[DIAGNOSTIC_MODE('All'|['GetCOPEntries','CheckConnectivity',
'CheckAuthentication','GetTPTSessions',
'TargetTableOrQuerySchema'])])
);
i have the following query and the problem is in the Case statement. It s being used in a Join condition. for some reason is bringing up both alternatives from the case
here s the code
SELECT C.GREGORIAN_MONTH_ID
,C.BUSINESS_PARTY_ID
,C.TOTAL_MONTO
,C.Capitas_Puntuales
,C.CUIT
,nb_apellido
,nb_oficial_actual
,nb_cne_obe
,nb_nodo
,nb_territorio
,cd_area_negocio
FROM (SELECT gregorian_month_id
,business_party_id
,Case when BUSINESS_PARTY_ID in (88888,200) then '9999999999999' else business_party_ident_num end CUIT
,SUM(amt_accum) Total_Monto
,count(*) Capitas_Puntuales
FROM dbsreg.A127932_PARTY_MAIN_PAYROLL_HISTORY
where gregorian_month_id= 201806
group by 1,2,3
) C
LEFT JOIN
(select NU_CUIT, nb_apellido,nb_oficial_actual, nb_cne_obe, nb_nodo, nb_territorio,cd_area_negocio
,(fh_corte/100 + 190000) gregorian_month_id
from dbsreg.a119527_base_info_gerencial
) G
on C.CUIT = G.NU_CUIT
and (case
when C.gregorian_month_id in (G.gregorian_month_id) then C.gregorian_month_id
else C.gregorian_month_id -1
END) = G.gregorian_month_id
ORDER BY C.BUSINESS_PARTY_ID
anyone can tell what s going on there?
You final query returns C.BUSINESS_PARTY_ID which is not transformed by Case. Your case statement also draws on BUSINESS_PARTY_ID. Did you mean to have C.CUIT instead of C.BUSINESS_PARTY_ID in your outer select statement?
long story short, i moved the case withing to a where statement from table C and added a userdefined value for the gregorian:
SELECT C.GREGORIAN_MONTH_ID
,C.BUSINESS_PARTY_ID
,C.TOTAL_MONTO
,C.Capitas_Puntuales
,C.CUIT
,nb_apellido
,nb_oficial_actual
,nb_cne_obe
,nb_nodo
,nb_territorio
,cd_area_negocio
FROM (SELECT gregorian_month_id
,business_party_id
,Case when BUSINESS_PARTY_ID in (88888,200) then '9999999999999' else business_party_ident_num end CUIT
,SUM(amt_accum) Total_Monto
,count(*) Capitas_Puntuales
FROM dbsreg.A127932_PARTY_MAIN_PAYROLL_HISTORY
where gregorian_month_id= ?FECHA_BASE
group by 1,2,3
) C
LEFT JOIN
(select NU_CUIT, nb_apellido,nb_oficial_actual, nb_cne_obe, nb_nodo, nb_territorio,cd_area_negocio
,(fh_corte/100 + 190000) gregorian_month_id
from dbsreg.a119527_base_info_gerencial
where gregorian_month_id = (Case when ?FECHA_BASE = (gregorian_month_id) then gregorian_month_id else gregorian_month_id-1 end )
) G
on C.CUIT = G.NU_CUIT
ORDER BY C.BUSINESS_PARTY_ID
I have:
PROCEDURE A
(
inId IN NUMBER,
RC1 OUT SYS_REFCURSOR
) IS
tMessage VARCHAR2(128);
BEGIN
OPEN RC1 FOR
SELECT * FROM
(
SELECT
a.company,
SUM(a.holding_balance) balance
FROM TableNameEntries A
WHERE
A.BATCH_ID = inId
GROUP BY a.company
)
ORDER BY balance DESC ;
EXCEPTION
WHEN OTHERS THEN
tMessage :='Exception ' || SQLCODE || ': ' || SQLERRM;
OPEN RC1 FOR
SELECT tMessage FROM DUAL;
END A;
For the balance column, I have values like -1, 0,1. Currently it's sorted like 1 0 -1, but I don't care about the zeros, so I want it to be like -1,1,0 or 1,-1,0
How do I do it in PL/SQL? I tried:
SELECT
a.company,
SUM(a.holding_balance) balance
FROM REC.CAG_GL_ENTRIES A
WHERE
A.BATCH_ID = 201311
order by case priority when 0 then 2 else 1 END priority
But it's saying PRIORITY is invalid identifier.
How can I get this to work?
Try:
ORDER BY CASE balance
WHEN 0 THEN null
ELSE balance
END
DESC NULLS LAST
there are two ways in your case (second is more common, first is more clear):
SELECT a.company,
SUM(a.holding_balance) balance
FROM REC.CAG_GL_ENTRIES A
WHERE A.BATCH_ID = 201311
order by abs(balance) desc;
SELECT a.company,
SUM(a.holding_balance) balance
FROM REC.CAG_GL_ENTRIES A
WHERE A.BATCH_ID = 201311
order by decode(balance,1,1,-1,1,2);
ORDER BY SIGN(ABS(balance)) DESC, balance
ABS() turns all the negatives to positives. SIGN() turns 0 to 0, >0 to 1 (and <0 to -1). Combined with DESC this puts all the zeros at the end and all the non-zeros above them in no particular order.
Then I sorted by the balance again to order the non-zeros.
You can also use
order by balance * balance desc
Oracle SQL Developer complains about next SQL though I can't seem to find the reason:
IF to_number(to_char(sysdate, 'HH24')) > 6 THEN
IF to_number(to_char(sysdate, 'HH24')) < 9 THEN
SELECT 1 FROM dual;
ELSE
SELECT (CASE WHEN result = 'SUCCESS' THEN 1 ELSE 0 END) FROM t_job WHERE to_char(start_time, 'yyyy/mm/dd') = to_char(sysdate, 'yyyy/mm/dd');
END IF;
ELSE
SELECT (CASE WHEN result = 'SUCCESS' THEN 1 ELSE 0 END) FROM t_job WHERE to_char(start_time, 'yyyy/mm/dd') = to_char(sysdate, 'yyyy/mm/dd');
END IF;
What's the mistake in provided query?
Error report:
Error starting at line 7 in command:
ELSE
Error report:
Unknown Command
(CASEWHENRESULT='SUCCESS'THEN1ELSE0END)
---------------------------------------
1
Error starting at line 9 in command:
END IF
Error report:
Unknown Command
There are a couple of problems with your code (which is PL/SQL, not just SQL):
1) You are missing the begin and end around the block.
2) Your selects need an into clause
try:
DECLARE
l_result number;
BEGIN
IF to_number(to_char(sysdate, 'HH24')) > 6 THEN
IF to_number(to_char(sysdate, 'HH24')) < 9 THEN
SELECT 1 INTO l_result FROM dual;
ELSE
SELECT (CASE WHEN result = 'SUCCESS' THEN 1 ELSE 0 END)
INTO l_result
FROM t_job WHERE to_char(start_time, 'yyyy/mm/dd') = to_char(sysdate, 'yyyy/mm/dd');
END IF;
ELSE
SELECT (CASE WHEN result = 'SUCCESS' THEN 1 ELSE 0 END)
INTO l_result
FROM t_job WHERE to_char(start_time, 'yyyy/mm/dd') = to_char(sysdate, 'yyyy/mm/dd');
END IF;
dbms_output.put_line('result is '||l_result);
END;
Since this is a PL/SQL block, your SELECT statements would need to select the data into some local variable or they would need to be used in a cursor. Which approach you want would depend on how many rows in T_JOB could potentially match the criteria you're specifying. Assuming all three statements would return exactly 1 row, you could do something like this (code simplified to avoid repeating the same query twice)
DECLARE
l_some_local_variable PLS_INTEGER;
BEGIN
IF( to_number( to_char( sysdate, 'HH24' ) ) > 6 and
to_number( to_char( sysdate, 'HH24' ) ) < 9 )
THEN
SELECT 1
INTO l_some_local_variable
FROM dual;
ELSE
SELECT (CASE WHEN result = 'SUCCESS'
THEN 1
ELSE 0
END)
INTO l_some_local_variable
FROM t_job
WHERE trunc( start_time ) = trunc( sysdate );
END IF;
END;
Of course, once you populate the data in your local variable, you would need to actually do something with the value. Potentially, you may want to create a function that returns the local variable rather than using an anonymous PL/SQL block as I have done here.