SQL need to add outerjoin to the query below - sql

In the below SQL:
I need to add two columns in the result
1) Local_code
2)Local_CPTY_SYS_ID,
which are in HSBC_LOCAL_INVOL_PARTY table.
So far I have tried to add
select local_code from HSBC_LOCAL_INVOL_PARTY
h join t_cdr T2
on T2.counterparty_new = h.entity_code
but that doesn't work. It needs an explicit outer join in the end. Please help
SELECT
T2.counterparty_new,
T2.bis_entity_type_original,
T2.counterparty_new_desc,
T2.counterparty_new_attribute_6,
T2.method_original,
T2.netting_agreement_reference,
T2.internal_rating_new,
T2.counterparty_type_original,
T2.obligor_grade_new,
T2.pd_pre_floor_new,
T2.pd_new,
T2.lgd,
T2.rwa
from t_cdr T2,
(
SELECT * FROM (
SELECT
FINAL.FILTER_MARKER,
FINAL.entity_code
FROM (
SELECT
FILTER_POP.entity_code,
FILTER_POP.FILTER_MARKER
FROM (
SELECT
CASE
WHEN CONCAT(Dlgd,unfloored_lgd) IS NOT NULL
THEN 'EXCLUDE'
WHEN CONCAT(Dlgd,unfloored_lgd) IS NULL
THEN 'INCLUDE'
END AS FILTER_MARKER,
entity_code,
Dlgd,
unfloored_lgd
FROM
HSBC_LOCAL_INVOL_PARTY
WHERE
((HSBC_LOCAL_INVOL_PARTY.entity_code) NOT LIKE '%DUM%')
AND
((HSBC_LOCAL_INVOL_PARTY.entity_code) NOT LIKE '%HSBC%')
) FILTER_POP
GROUP BY
FILTER_POP.entity_code,
FILTER_POP.FILTER_MARKER) FINAL
GROUP BY
FINAL.FILTER_MARKER,
FINAL.entity_code
ORDER BY
FINAL.entity_code)
PIVOT
(
COUNT(FILTER_MARKER)
FOR FILTER_MARKER IN ('INCLUDE' AS INCLUDE,'EXCLUDE' AS EXCLUDE)
)
WHERE INCLUDE = 1 AND EXCLUDE = 0
) ENTITY_FILTER
WHERE ENTITY_FILTER.entity_code = T2.counterparty_new
AND T2.method_original = 'ADV'
ORDER BY T2.rwa DESC

Solved it: Look at the last few lines. Took a while but optimized it as well for performance.
SELECT
T2.counterparty_new,
T2.bis_entity_type_original,
T2.counterparty_new_desc,
T2.counterparty_new_attribute_6,
T2.method_original,
T2.netting_agreement_reference,
T2.internal_rating_new,
T2.counterparty_type_original,
T2.obligor_grade_new,
T2.pd_pre_floor_new,
T2.pd_new,
T2.lgd,
HSBC_LOCAL_INVOL_PARTY.local_code,
T2.rwa
from t_cdr T2,
(
SELECT * FROM (
SELECT
FINAL.FILTER_MARKER,
FINAL.entity_code
FROM (
SELECT
FILTER_POP.entity_code,
FILTER_POP.FILTER_MARKER
FROM (
SELECT
CASE
WHEN CONCAT(Dlgd,unfloored_lgd) IS NOT NULL
THEN 'EXCLUDE'
WHEN CONCAT(Dlgd,unfloored_lgd) IS NULL
THEN 'INCLUDE'
END AS FILTER_MARKER,
entity_code,
Dlgd,
unfloored_lgd
FROM
HSBC_LOCAL_INVOL_PARTY
WHERE
((HSBC_LOCAL_INVOL_PARTY.entity_code) NOT LIKE '%DUM%')
AND
((HSBC_LOCAL_INVOL_PARTY.entity_code) NOT LIKE '%HSBC%')
) FILTER_POP
GROUP BY
FILTER_POP.entity_code,
FILTER_POP.FILTER_MARKER) FINAL
GROUP BY
FINAL.FILTER_MARKER,
FINAL.entity_code
ORDER BY
FINAL.entity_code)
PIVOT
(
COUNT(FILTER_MARKER)
FOR FILTER_MARKER IN ('INCLUDE' AS INCLUDE,'EXCLUDE' AS EXCLUDE)
)
WHERE INCLUDE = 1 AND EXCLUDE = 0
) ENTITY_FILTER,HSBC_LOCAL_INVOL_PARTY
WHERE ENTITY_FILTER.entity_code = T2.counterparty_new
AND ENTITY_FILTER.entity_code = HSBC_LOCAL_INVOL_PARTY.entity_code(+)
AND T2.method_original = 'ADV'
ORDER BY T2.rwa DESC

Related

how to delete repeated values in UNION query using count

Hello I have been trying to delete a repeated value on the following UNION query with the following results (image). How can I filter out the value LW_ID=8232 with AANTALLN =0. I need to find a way taht if in the first query AANTALLN >0 is found, then on the second part of the union query not insert it again. Thanks "
With LESEENHEIDLOOPBAAN as (
SELECT
LE_AGENDA_FK,
LE_CODE,
LE_ID,
LE_KLAS_FK,
LE_KLASPARTITIE_FK,
LE_OMSCHRIJVING,
LE_VERANDERDDOOR,
LE_VERANDERDOP,
Count(LH_ID) As AantalLln
FROM
LESEENHEID
INNER JOIN LOOPBAANLESEENHEID on (LH_LESEENHEID_FK = LE_ID)
INNER JOIN LOOPBAAN ON (LH_LOOPBAAN_FK = LB_ID)
WHERE
(
'2022/09/28' BETWEEN LB_VAN
AND LB_TOT
)
AND (
LE_ID in (8277, 8276, 8232)
)
GROUP BY
LE_AGENDA_FK,
LE_CODE,
LE_ID,
LE_KLAS_FK,
LE_KLASPARTITIE_FK,
LE_OMSCHRIJVING,
LE_VERANDERDDOOR,
LE_VERANDERDOP
),
LESEENHEIDLOOPBAANNULL AS (
SELECT
LE_AGENDA_FK,
LE_CODE,
LE_ID,
LE_KLAS_FK,
LE_KLASPARTITIE_FK,
LE_OMSCHRIJVING,
LE_VERANDERDDOOR,
LE_VERANDERDOP,
0 As AantalLln
FROM
LESEENHEID
where
LE_ID in (8277, 8276, 8232)
and EXISTS (
SELECT
*
FROM
LESEENHEIDLOOPBAAN
)
)
SELECT
*
FROM
LESEENHEIDLOOPBAAN
UNION
SELECT
*
FROM
LESEENHEIDLOOPBAANNULL ROWS 1000
Try this out using ROW_NUMBER:
SELECT * FROM (
SELECT
ROW_NUMBER () OVER (PARTITION BY LW_ID ORDER BY AANTALLN DESC) AS RN
,* FROM
(
SELECT * FROM
LESEENHEIDLOOPBAAN
UNION
SELECT
*
FROM
LESEENHEIDLOOPBAANNULL ROWS 1000
)
)
) WHERE RN = 1
This way you eliminate the duplicates.

How to merge two columns from CASE STATEMENT of DIFFERENT CONDITION

My expected result should be like
----invoiceNo----
T17080003,INV14080011
But right now, I've come up with following query.
SELECT AccountDoc.jobCode,AccountDoc.shipmentSyskey,AccountDoc.docType,
CASE AccountDoc.docType
WHEN 'M' THEN
JobInvoice.invoiceNo
WHEN 'I' THEN
(STUFF((SELECT ', ' + RTRIM(CAST(AccountDoc.docNo AS VARCHAR(20)))
FROM AccountDoc LEFT OUTER JOIN JobInvoice
ON AccountDoc.principalCode = JobInvoice.principalCode AND
AccountDoc.jobCode = JobInvoice.jobCode
WHERE (AccountDoc.isCancelledByCN = 0)
AND (AccountDoc.docType = 'I')
AND (AccountDoc.jobCode = #jobCode)
AND (AccountDoc.shipmentSyskey = #shipmentSyskey)
AND (AccountDoc.principalCode = #principalCode) FOR XML
PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,' '))
END AS invoiceNo
FROM AccountDoc LEFT OUTER JOIN JobInvoice
ON JobInvoice.principalCode = AccountDoc.principalCode AND
JobInvoice.jobCode = AccountDoc.jobCode
WHERE (AccountDoc.jobCode = #jobCode)
AND (AccountDoc.isCancelledByCN = 0)
AND (AccountDoc.shipmentSyskey = #shipmentSyskey)
AND (AccountDoc.principalCode = #principalCode)
OUTPUT:
----invoiceNo----
T17080003
INV14080011
Explanation:
I want to select docNo from table AccountDoc if AccountDoc.docType = I.
Or select invoiceNo from table JobInvoice if AccountDoc.docType = M.
The problem is what if under same jobCode there have 2 docType which are M and I, how I gonna display these 2 invoices?
You can achieve this by using CTE and FOR XML. below is the sample code i created using similar tables you have -
Create table #AccountDoc (
id int ,
docType char(1),
docNo varchar(10)
)
Create table #JobInvoice (
id int ,
invoiceNo varchar(10)
)
insert into #AccountDoc
select 1 , 'M' ,'M1234'
union all select 2 , 'M' ,'M2345'
union all select 3 , 'M' ,'M3456'
union all select 4 , 'I' ,'I1234'
union all select 5 , 'I' ,'I2345'
union all select 6 , 'I' ,'I3456'
insert into #JobInvoice
select 1 , 'INV1234'
union all select 2 , 'INV2345'
union all select 3 , 'INV3456'
select *
from #AccountDoc t1 left join #JobInvoice t2
on t1.id = t2.id
with cte as
(
select isnull( case t1.docType WHEN 'M' THEN t2.invoiceNo WHEN 'I' then
t1.docNo end ,'') invoiceNo
from #AccountDoc t1 left join #JobInvoice t2
on t1.id = t2.id )
select invoiceNo + ',' from cte For XML PATH ('')
You need to pivot your data if you have situations where there are two rows, and you want two columns. Your sql is a bit messy, particularly the bit where you put an entire select statement inside a case when in the select part of another query. These two queries are virtually the same, you should look for a more optimal way of writing them. However, you can wrap your entire sql in the following:
select
Jobcode, shipmentsyskey, [M],[I]
from(
--YOUR ENTIRE SQL GOES HERE BETWEEN THESE BRACKETS. Do not alter anything else, just paste your entire sql here
) yoursql
pivot(
max(invoiceno)
for docType in([M],[I])
)pvt

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.)

Need help creating SQL query from example of data

I have a database table below.
And I want to get list of all DBKey that have: at least one entry with Staled=1, and the last entry is Staled=0
The list should not contain DBKey that has only Staled=0 OR Staled=1.
In this example, the list would be: DBKey=2 and DBKey=3
I think this should do the trick:
SELECT DISTINCT T.DBKey
FROM TABLE T
WHERE
-- checks that the DBKey has at least one entry with Staled = 1
EXISTS (
SELECT DISTINCT Staled
FROM TABLE
WHERE DBKey = T.DBKey
AND Staled = 1
)
-- checks that the last Staled entry for this DBKey is 0
AND EXISTS (
SELECT DISTINCT Staled
FROM TABLE
WHERE DBKey = T.DBKey
AND Staled = 0
AND EntryDateTime = (
SELECT MAX(EntryDateTime)
FROM TABLE
WHERE DBKey = T.DBKey
)
)
Here is a working SQLFiddle of the query, using your sample data.
The idea is to use EXISTS to look for those individual conditions that you've described. I've added comments to my code to explain what each does.
Should be done with a simple JOIN... Starting FIRST with any 1 qualifiers, joined to itself by same key AND 0 staled qualifier AND the 0 record has a higher date. Ensure you have an index on ( DBKey, Staled, EntryDateTime )
SELECT
YT.DBKey,
MAX( YT.EntryDateTime ) as MaxStaled1,
MAX( YT2.EntryDateTime ) as MaxStaled0
from
YourTable YT
JOIN YourTable YT2
ON YT.DBKey = YT2.DBKey
AND YT2.Staled = 0
AND YT.EntryDateTime < YT2.EntryDateTime
where
YT.Staled = 1
group by
YT.DBKey
having
MAX( YT.EntryDateTime ) < MAX( YT2.EntryDateTime )
Maybe this:
With X as
(
Select Row_Number() Over (Partition By DBKey Order By EntryDateTime Desc) RN, DBKey, Staled
From table
)
Select *
From X
Where rn = 1 and staled = 0 and
Exists (select 1 from x x2 where x2.dbkey = x.dbkey and Staled = 1)

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.