How do I create a conditional SQL query - sql

I am trying to create an Oracle Sql query using IF/Else statements
IF EXISTS
(
SELECT *
FROM baninst1.an_employee_position
WHERE baninst1.an_employee_position.person_uid = 593791
AND baninst1.an_employee_position.position_end_date IS NULL) THEN
SELECT *
FROM baninst1.an_employee_position
WHERE baninst1.an_employee_position.person_uid = 593791
AND (
baninst1.an_employee_position.position_end_date IS NULL
OR baninst1.an_employee_position.position_end_date > SYSDATE)
AND baninst1.an_employee_position.effective_start_date <= SYSDATE;ELSE
SELECT *
FROM (
SELECT *
FROM baninst1.an_employee_position
WHERE baninst1.an_employee_position.person_uid = 593791 )
WHERE ROWNUM = 1;END IF;
However I receive an "Unknown Command" error when I run it. No more error information

This may provide what you are looking for:
SELECT a.*
FROM employee_position a
where person_uid = 593791
and (
(a.position_end_date is null)
or
(
a.position_end_date =
(select max(position_end_date)
from employee_position b
where b.person_uid = a.person_uid
and b.position_end_date is not null
)
)
)
Another way
SELECT a.*
FROM employee_position a
where person_uid = 593791
and (
nvl(a.position_end_date, trunc(sysdate+100)) >=
(select max(position_end_date)
from employee_position b
where b.person_uid = a.person_uid
and b.position_end_date is not null
)
)

Related

TERADATA, CASE INTO WHERE CLAUSE

I'd need help on this matter.
my where condition does not get accepted ... I know that is tricky the case in the where clause, so i think you could let me out... I created a field into a subquery with a over partition by, which then i bring into the main select ... then I'd need to apply the filter you see below... it returns me an error saying that B does not exist even tough if I just write B.CC = 1 then it gives me result...
any ideas?
Thanks in advance
SELECT
B.*
FROM
(
SELECT
A.*,
(Count(A.COD_ABI) Over (PARTITION BY A.COD_ABI, A.COD_KTO)) AS CC
FROM (
SELECT DISTINCT
T2.COD_PRODT_SALDO,
T2.COD_RESID_NPE,
T2.COD_DIVISA_UIC,
T2.COD_ABI,
T2.COD_NDG,
T2.COD_KTO,
T2.COD_PAESE_UIC_NPE,
T2.DAT_SCA,
T2.DAT_ACC,
T2.DAT_EST
FROM
(
SELECT
T1.COD_PRODT_SALDO
,T1.COD_RESID_NPE
,T1.COD_DIVISA_UIC
,T1.COD_ABI
,T1.COD_NDG
,'00753' ||T1.COD_PRODT_SALDO||T1.COD_CNTRT_SALDO AS COD_KTO
,T1.COD_CONTRATTO_SAL
,T1.COD_RIFER_ANNO
,T1.COD_RIFER_MESE
,T1.COD_RIFER_ANNO || T1.COD_RIFER_MESE AS COD_RIFER
,T1.COD_CONTB_ETR
,T1.DAT_EST
,T1.DAT_ACC
,T1.DAT_SCA
,T1.COD_PAESE_UIC_NPE
FROM ES777A.VA_ES_DB_ANAGR_CONTO AS T1,
ES777A.VE_BFD_PDC AS T2
WHERE T1.TMS_INIZIO_VALIDITA <= T2.TMS_PDC
AND T1.TMS_FINE_VALIDITA > T2.TMS_PDC
AND T1.TMS_CANC_FISICA IS NULL
AND T1.FLG_RIFACIMENTO = 0
AND T1.COD_ABI = T2.COD_ABI
AND T2.NOM_VISTA='VA_ES_DB_ANAGR_CONTO'
AND T2.NUM_PERIO_RIF = 20200131
AND T2.COD_PERIODICITA = 'G'
AND T1.COD_PRODT_SALDO NOT IN ('1398' , '1698')
AND T1.COD_PRODT_SALDO IN ('1801', '1803', '1901', '1903', '3301', '3304', '3311', '3401', '3411', '3421')
)
AS T2
INNER JOIN
(
SELECT
T1.COD_ABI,
'00753'||T1.COD_PRODT_SALDO||T1.COD_CNTRT_SALDO AS COD_KTO,
Max(T1.COD_RIFER_ANNO || COD_RIFER_MESE) AS MAX_COD_RIFER
FROM ES777A.VA_ES_DB_ANAGR_CONTO AS T1,
ES777A.VE_BFD_PDC AS T2
WHERE
T1.TMS_INIZIO_VALIDITA <= T2.TMS_PDC
AND T1.TMS_FINE_VALIDITA > T2.TMS_PDC
AND T1.TMS_CANC_FISICA IS NULL
AND T1.FLG_RIFACIMENTO = 0
AND T1.COD_ABI = T2.COD_ABI
AND T2.NOM_VISTA = 'VA_ES_DB_ANAGR_CONTO'
AND T2.NUM_PERIO_RIF = 20200131
AND T2.COD_PERIODICITA = 'G'
AND T1.COD_PRODT_SALDO NOT IN ('1398' , '1698')
AND T1.COD_PRODT_SALDO IN ('1801', '1803', '1901', '1903', '3301', '3304', '3311', '3401', '3411', '3421')
GROUP BY T1.COD_PRODT_SALDO,T1.COD_ABI,T1.COD_CNTRT_SALDO
)
AS T1
ON ( T2.COD_ABI = T1.COD_ABI AND T2.COD_KTO = T1.COD_KTO AND T2.COD_RIFER = T1.MAX_COD_RIFER )
WHERE
( T2.DAT_EST > '2019-11-02' OR T2.DAT_EST IS NULL ) -- -90GG
AND ( T2.DAT_SCA > '2019-11-02' OR T2.DAT_SCA IS NULL ) -- -90GG
)
A
)
B
WHERE b.cc =
WHEN (B.CC > 1 AND B.DAT_EST IS NOT NULL) THEN 1
WHEN (B.CC > 1 AND B.DAT_EST IS NULL) THEN 0
WHEN (B.CC = 1) THEN 1 ELSE 0
END
This answers the original version of the question.
In Teradata, you can simplify the logic to:
SELECT ...,
Count(A.COD_ABI) Over (PARTITION BY A.COD_ABI, A.COD_KTO) AS CC
FROM A
QUALIFY CC > 1 AND DATE_EST IS NOT NULL;
All the subqueries are unnecessary

How can i tune this select statement to prevent it from having select from same table many times?

I need to tune this sql statement provided by developer, how can I speed it up and prevent the HAVING part from select from same users table many time?
SELECT *
FROM (
SELECT t.*, ROWNUM pageination__row__123__
FROM (
SELECT *
FROM (
SELECT SUM(rcm) sum_rcm, SUM(real_amount) sum_ra, MIN(min_share) min_share, MAX(max_share) max_share, SUM(DECODE(rcm_flag, 'Y', 0, rcm)) rcm_n, b.parentid
FROM bet_total b
WHERE draw_date BETWEEN :1 AND :2
GROUP BY parentid
HAVING (
parentid
IN (
SELECT id FROM users u2,
(
SELECT u3.path
FROM users u3
WHERE u3.type = 2 AND u3.lv = 1 AND u3.tesing = 0 AND u3.user_key = :3
) q
WHERE u2.path BETWEEN q.path AND q.path || chr(to_number('FFFFFFFF', 'xxxxxxxx')) AND u2.type = 2
) AND SUM(rcm) > :4
)
) b1, users u5
WHERE (b1.parentid = u5.id AND rcm_n > 0 )
ORDER BY u5.path
) t
) t
WHERE t.pageination__row__123__ <= :5;
SQL Execution Plan
Index of the table Bet_total
Index of table users
You could try using the WITH-Clause.

Translating SQL Server 'OUTPUT' to Oracle?

I am having big issues translating my MSSQL (sql-server) query to Oracle (PL-SQL).
The goal is to do an update and a select on the updated field in one threadsafe operation.
My current MSSQL query:
UPDATE PDFCONVERT_G
SET PDF_STATUS = 1, PDF_STARTDATE = GETDATE(), PDF_CONVERTERNAME='inputConverterName'
OUTPUT Inserted.PDF_ACTION as Action,
Inserted.PDF_ARKMERK_VE As ARKMERK,
Inserted.PDF_TYPE_DL as DlTypeDT,
Inserted.PDF_DOKID_VE as DocId,
Inserted.PDF_DOKMALID_VE as DOKMALID,
Inserted.PDF_FILREF_VE as FILREF,
Inserted.PDF_FILTYPE_LF as Filtype,
Inserted.PDF_JPID_JP as JpId,
Inserted.PDF_LOCFILREF_VE as LOCFILREF,
Inserted.PDF_SAID_SA as SaId,
Inserted.PDF_SJEKKETUT_VE as SJEKKETUT,
Inserted.PDF_TGKODE_VE as TGKODE,
Inserted.PDF_VARIANT_VE as Variant,
Inserted.PDF_VERSJON_VE as Version,
Inserted.PDF_CHECKINAFTERCONVERT as CheckinAfterConvert
FROM PDFCONVERT_G t1
INNER JOIN (
SELECT TOP(1) *
FROM PDFCONVERT_G A WHERE (
(A.PDF_LAGRENH_VE = 'PROD' OR EXISTS(SELECT * FROM PDFCONVERT_G B WHERE A.PDF_JOBID=B.PDF_JOBID AND B.PDF_LAGRENH_VE='PROD' AND B.PDF_ACTION='MERGE'))
AND PDF_STATUS = 0 AND NOT EXISTS(
SELECT * FROM PDFCONVERT_G B where a.pdf_jobid = b.pdf_jobid and b.pdf_status > 0 and a.pdf_action != b.pdf_action))
ORDER BY A.PDF_PRIORITY DESC, A.PDF_JOBID, A.PDF_RNR
) t2 ON t2.PDF_JOBID = t1.PDF_JOBID
I can simply do this query in my .net code and the result will be the Output variables.
I know Oracle has the RETURNING INTO syntax but concidering how complex my WHERE clause is I simply get syntax errors all the time.
I would prefer to write a query without creating a function but even if I have to do that, I am having issues.
SELECT TOP(1) *
FROM PDFCONVERT_G A
WHERE (
( A.PDF_LAGRENH_VE = 'PROD'
OR EXISTS(SELECT *
FROM PDFCONVERT_G B
WHERE A.PDF_JOBID=B.PDF_JOBID
AND B.PDF_LAGRENH_VE='PROD'
AND B.PDF_ACTION='MERGE')
)
AND PDF_STATUS = 0
AND NOT EXISTS(
SELECT *
FROM PDFCONVERT_G B
where a.pdf_jobid = b.pdf_jobid
and b.pdf_status > 0
and a.pdf_action != b.pdf_action
)
)
ORDER BY A.PDF_PRIORITY DESC, A.PDF_JOBID, A.PDF_RNR
Can be rewritten (without the correlated sub-queries) as:
SELECT *
FROM (
SELECT a.*,
ROW_NUMBER() OVER ( ORDER BY PDF_PRIORITY DESC, PDF_JOBID, PDF_RNR ) AS rn
FROM (
SELECT a.*,
COUNT(
CASE WHEN DF_LAGRENH_VE = 'PROD'
AND PDF_ACTION = 'MERGE'
THEN 1 END
) OVER ( PARTITION BY pdf_jobid )
AS num_prod_merge,
COUNT(
CASE WHEN pdf_status > 0 THEN 1 END
) OVER ( PARTITION BY pdf_jobid )
AS num_all_actions,
COUNT(
CASE WHEN pdf_status > 0 THEN 1 END
) OVER ( PARTITION BY pdf_jobid, pdf_action )
AS num_same_actions
FROM PDFCONVERT_G a
) a
WHERE ( PDF_LAGRENH_VE = 'PROD' OR num_prod_merge > 0 )
AND PDF_STATUS = 0
AND num_all_actions = num_same_actions
)
WHERE rn = 1;
You can then rewrite your UPDATE to something like:
UPDATE PDFCONVERT_G
SET PDF_STATUS = 1,
PDF_STARTDATE = SYSDATE,
PDF_CONVERTERNAME='inputConverterName'
WHERE ROWID = (
SELECT ROWID
FROM (
-- as above
)
WHERE rn = 1
)
RETURNING PDF_ACTION -- , ...
INTO :Action -- , ...
(Note: Unable to test this at the moment so there may be some small syntax errors but you should get the general idea.)

Subquery within SubQuery in SQL - DB2

I am having issue when trying to make a the sub query shown in the first filter dynamically based on one of the results returned from the query. Can someone please tell me what I am doing wrong. In the first subquery it worked.
( SELECT
MAX( MAX_DATE - MIN_DATE ) AS NUM_CONS_DAYS
FROM
(
SELECT
MIN(TMP.D_DAT_INDEX_DATE) AS MIN_DATE,
MAX(TMP.D_DAT_INDEX_DATE) AS MAX_DATE,
SUM(INDEX_COUNT) AS SUM_INDEX
FROM
(
SELECT
D_DAT_INDEX_DATE,
INDEX_COUNT,
D_DAT_INDEX_DATE - (DENSE_RANK() OVER(ORDER BY D_DAT_INDEX_DATE)) DAYS AS G
FROM
DWH.MQT_SUMMARY_WATER_READINGS
WHERE
N_COD_METER_CNTX_KEY = 79094
) AS TMP
GROUP BY
TMP.G
ORDER BY
1
) ) AS MAX_NUM_CONS_DAYS
Above is the subquery I am trying to replace 123456 with CTXTKEY or CTXT.N_COD_METER_CNTX_KEY from query. Below is the full code. Please note than in the subquery before "MAX_NUM_CONS_DAYS" it worked. However, it was only one subquery down.
SELECT
N_COD_WM_DWH_KEY,
V_COD_WM_SN_2,
N_COD_SP_ID,
CTXKEY,
V_COD_MIU_SN,
N_COD_POD,
MIU_CAT,
V_COD_SITR_ASSOCIATED,
WO_INST_DATE,
WO_MIU_CAT,
DAYSRECEIVED3,
MAX_NUM_CONS_DAYS,
( CASE WHEN ( DAYSRECEIVED3 = 3 ) THEN 'Y' ELSE 'N' END ) AS GREEN,
( CASE WHEN ( DAYSRECEIVED3 < 3 AND DAYSRECEIVED3 > 0 ) THEN 'Y' ELSE 'N' END ) AS BLUE,
( CASE WHEN ( DAYSRECEIVED3 = 0 AND MAX_NUM_CONS_DAYS >= 5 ) THEN 'Y' ELSE 'N' END ) AS ORANGE,
( CASE WHEN ( DAYSRECEIVED3 = 0 AND MAX_NUM_CONS_DAYS BETWEEN 1 and 4 ) THEN 'Y' ELSE 'N' END ) AS RED
FROM
(
SELECT
WMETER.N_COD_WM_DWH_KEY,
WMETER.V_COD_WM_SN_2,
WMETER.N_COD_SP_ID,
CTXT.N_COD_METER_CNTX_KEY AS CTXKEY,
CTXT.V_COD_MIU_SN,
CTXT.N_COD_POD,
MIU.N_COD_MIU_CATEGORY AS MIU_CAT,
CTXT.V_COD_SITR_ASSOCIATED,
T1.D_DAT_PLAN_INST AS WO_INST_DATE,
T1.N_COD_MIU_CATEGORY AS WO_MIU_CAT,
( SELECT COUNT( DISTINCT D_DAT_INDEX_DATE ) FROM DWH.MQT_SUMMARY_WATER_READINGS WHERE ( N_COD_METER_CNTX_KEY = CTXT.N_COD_METER_CNTX_KEY ) AND D_DAT_INDEX_DATE BETWEEN ( '2013-07-10' ) AND ( '2013-07-12' ) ) AS DAYSRECEIVED3,
( SELECT
MAX( MAX_DATE - MIN_DATE ) AS NUM_CONS_DAYS
FROM
(
SELECT
MIN(TMP.D_DAT_INDEX_DATE) AS MIN_DATE,
MAX(TMP.D_DAT_INDEX_DATE) AS MAX_DATE,
SUM(INDEX_COUNT) AS SUM_INDEX
FROM
(
SELECT
D_DAT_INDEX_DATE,
INDEX_COUNT,
D_DAT_INDEX_DATE - (DENSE_RANK() OVER(ORDER BY D_DAT_INDEX_DATE)) DAYS AS G
FROM
DWH.MQT_SUMMARY_WATER_READINGS
WHERE
N_COD_METER_CNTX_KEY = 79094
) AS TMP
GROUP BY
TMP.G
ORDER BY
1
) ) AS MAX_NUM_CONS_DAYS
FROM DWH.DWH_WATER_METER AS WMETER
LEFT JOIN DWH.DWH_WMETER_CONTEXT AS CTXT
ON WMETER.N_COD_WM_DWH_KEY = CTXT.N_COD_WM_DWH_KEY
LEFT JOIN DWH.DWH_MIU AS MIU
ON CTXT.V_COD_MIU_SN = MIU.V_COD_MIU_SN
LEFT JOIN
( SELECT V_COD_CORR_WAT_METER_SN, D_DAT_PLAN_INST, N_COD_MIU_CATEGORY
FROM DWH.DWH_ORDER_MANAGEMENT_FACT
JOIN DWH.DWH_MIU
ON DWH.DWH_ORDER_MANAGEMENT_FACT.V_COD_MIU_SN = DWH.DWH_MIU.V_COD_MIU_SN
) AS T1
ON WMETER.V_COD_WM_SN_2 = T1.V_COD_CORR_WAT_METER_SN
WHERE
( V_COD_SITR_ASSOCIATED = 'X' )
AND ( ( MIU.N_COD_MIU_CATEGORY <> 4 ) OR ( ( MIU.N_COD_MIU_CATEGORY IS NULL ) AND ( ( T1.N_COD_MIU_CATEGORY <> 4 ) OR ( T1.N_COD_MIU_CATEGORY IS NULL ) ) ) )
)
Error I am getting is:
Error Code: -204, SQL State: 42704
I would say that a good option here would be to use a CTE, or Common Table Expression. You can do something similar to the following:
WITH CTE_X AS(
SELECT VAL_A
,VAL_B
FROM TABLE_A)
,CTE_Y AS(
SELECT VAL_C
,VAL_B
FROM TABLE_B)
SELECT VAL_A
,VAL_B
FROM CTE_X X
JOIN CTE_Y Y
ON X.VAL_A = Y.VAL_C;
While this isn't specific to your example, it does show that CTE's create a sort of temporary "in memory" table that you can access in a subsequent query. This should allow you to issue your inner two subselects as a CTE, and then use the CTE in the "SELECT MAX( MAX_DATE - MIN_DATE ) AS NUM_CONS_DAYS" query.
You cannot reference columns from the outer select in the subselect, no more than 1 level deep anyway. If I correctly understand what you're doing, you'll probably need to join DWH.MQT_SUMMARY_WATER_READINGS and DWH.DWH_WMETER_CONTEXT in the outer select.

Need help on how to convert this select to a DELETE statement:

I need help as to how to convert this select to a delete statement.
SELECT stud_term_sum_div.id_num,
stud_term_sum_div.hrs_enrolled,
stud_term_sum_div.transaction_sts,
student_crs_hist.crs_cde,
student_crs_hist.transaction_sts
FROM stud_term_sum_div,
student_crs_hist
WHERE ( stud_term_sum_div.yr_cde = student_crs_hist.yr_cde ) and
( stud_term_sum_div.trm_cde = student_crs_hist.trm_cde ) and
( stud_term_sum_div.id_num = student_crs_hist.id_num ) and
( ( stud_term_sum_div.yr_cde = '2013' ) AND
( stud_term_sum_div.trm_cde = 'FA' ) AND
( stud_term_sum_div.hrs_enrolled >= 3.00 ) AND
( student_crs_hist.transaction_sts = 'D' ) )
The most straight-forward conversion is below:
DELETE * FROM stud_term_sum_div
WHERE ( stud_term_sum_div.yr_cde = student_crs_hist.yr_cde ) and
( stud_term_sum_div.trm_cde = student_crs_hist.trm_cde ) and
( stud_term_sum_div.id_num = student_crs_hist.id_num ) and
( ( stud_term_sum_div.yr_cde = '2013' ) AND
( stud_term_sum_div.trm_cde = 'FA' ) AND
( stud_term_sum_div.hrs_enrolled >= 3.00 ) AND
( student_crs_hist.transaction_sts = 'D' ) )
BUT, before you go executing that, please check that the WHERE clause really contains the conditions to be used for deletion. Note that this SQL statement will delete the entire row (a/k/a record) when the attributes in the WHERE clause satisfy the stated conditions.
If you only want to remove the data from the attributes (as opposed to the entire record), you'd need to use an SQL UPDATE statement instead. The (simplified) syntax for that is as follows:
UPDATE <table_name>
SET <attribute1> = <value1>
[, SET <attribute_n> = <value_n>...]
WHERE <conditions on which the record should be updated>
Doing a search on Bing, google, <insert your favorite search engine here> for "SQL DELETE" or "SQL UPDATE" should get you all the information you need (e.g. MSDN, for one).