I get ORA-00905: missing keyword - sql

I write this query and when I run it I get
ORA-00905: missing keyword
I check with many online SQL query checker and all of them answered it is correct can any body help me what's the problem
select *
from T_TimelineItem ti
where ti.C_HIDE = 0
and ti.F_RELATED_BUSINESS = 4335
and exists(select *
from T_Business b
inner join MM_BIZ_GUILDS g on b.C_ID = g.ID1
where b.C_ID = ti.F_RELATED_BUSINESS
and g.ID2 in (49))
and (CASE ti.C_TYPE
WHEN 1 then ti.C_ID in (select po.C_TIMELINEID
from T_PRODUCT pr
inner join T_POST po on po.C_ID = pr.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and pr.F_GUILD in (49))
WHEN 8 THEN ti.C_ID in (select po.C_TIMELINEID
from T_COMPETITION com
inner join T_POST po on po.C_ID = com.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and com.F_GUILD in (49)) END);

Don't use case in where clauses
and (ti.C_TYPE = 1 and ti.C_ID in (select po.C_TIMELINEID
from T_PRODUCT pr
inner join T_POST po on po.C_ID = pr.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and pr.F_GUILD in (49)))
or (ti.C_TYPE = 8 and ti.C_ID in (select po.C_TIMELINEID
from T_COMPETITION com
inner join T_POST po on po.C_ID = com.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and com.F_GUILD in (49)) END))

I have removed multiple in cause you can use equal easily for single value comparison and you don't need to select all the column inside exists
select *
from T_TimelineItem ti
where ti.C_HIDE = 0
and ti.F_RELATED_BUSINESS = 4335
and exists(select 1
from T_Business b
inner join MM_BIZ_GUILDS g on b.C_ID = g.ID1
where b.C_ID = ti.F_RELATED_BUSINESS
and g.ID2 = 49
)
and (ti.C_TYPE=1
and ti.C_ID in (select po.C_TIMELINEID
from T_PRODUCT pr
inner join T_POST po
on po.C_ID = pr.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and pr.F_GUILD =49
)
or ( ti.C_TYPE=8 and
ti.C_ID in (select po.C_TIMELINEID
from T_COMPETITION com
inner join T_POST po on po.C_ID = com.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and com.F_GUILD =49
)

Related

Left outer join invalid identifier

I can't seem to get these left outer joins right using derived tables. I need to do it this way as I need to use a subquery in the qualification.
The error I am receiving is ORA-00904: "E"."ENCNTR_ID": invalid identifier
I've tried moving the position of the join around and reversing the columns around the =. There's plenty of posts out there related to this but none of them have provided me the answer. Many are in regards to having multiple tables comma delimited in the FROM clause but my query doesn't have that.
SELECT
E.ENCNTR_ID
,E.REASON_FOR_VISIT
-- ,D.DIAGNOSIS_DISPLAY AS DISCHARGE_DX
-- ,D.DIAG_FTDESC AS WORKING_DX
,cclsql_cnvtdatetimeutc(E.REG_DT_TM, 2, 126) as reg_dt_tm
,cclsql_cnvtdatetimeutc(E.DISCH_DT_TM, 2, 126) as disch_dt_tm
,FACILITY.DISPLAY AS FACILITY
,P.PERSON_ID
,P.NAME_FULL_FORMATTED
,cclsql_cnvtdatetimeutc(P.BIRTH_DT_TM, 2, P.BIRTH_TZ) as birth_dt_tm
,MRN.ALIAS AS MRN
,FIN.ALIAS AS FIN
,ENC_TYPE.DISPLAY AS ENCOUNTER_TYPE
,NURSE_UNIT.DISPLAY AS NURSE_UNIT
,ROOM.DISPLAY AS ROOM
,BED.DISPLAY AS BED
,ADMITDOC_NAME.NAME_FULL_FORMATTED AS ADMITDOC_NAME
,DCDOC_NAME.NAME_FULL_FORMATTED AS DCDOC_NAME
,ADMIT_SRC.DISPLAY AS ADMIT_SOURCE
,ADMIT_TYPE.DISPLAY AS ADMIT_TYPE
,ESDP.RESULT_VAL AS ESDP
,DISCH_DISPOSITION.DISPLAY AS DISCH_DISPOSITION
FROM ENCOUNTER E
-- JOIN DISCHARGE D ON (D.ENCNTR_ID = E.ENCNTR_ID)
-- AND D.ACTIVE_IND = 1
-- AND D.END_EFFECTIVE_DT_TM > SYSDATE
JOIN PERSON P ON (P.PERSON_ID = E.PERSON_ID)
JOIN CODE_VALUE ENC_TYPE ON (ENC_TYPE.CODE_VALUE = E.ENCNTR_TYPE_CLASS_CD)
JOIN ENCNTR_ALIAS FIN ON (FIN.ENCNTR_ID = E.ENCNTR_ID)
AND FIN.ENCNTR_ALIAS_TYPE_CD = 1077 -- FIN CODE
AND FIN.ACTIVE_IND = 1
AND FIN.ACTIVE_STATUS_CD = 188
JOIN ENCNTR_ALIAS MRN ON (MRN.ENCNTR_ID = E.ENCNTR_ID)
AND MRN.ENCNTR_ALIAS_TYPE_CD = 1079 -- MRN CODE
AND MRN.ACTIVE_IND = 1
AND MRN.ACTIVE_STATUS_CD = 188
JOIN CODE_VALUE FACILITY on (FACILITY.CODE_VALUE = E.LOC_FACILITY_CD)
JOIN CODE_VALUE NURSE_UNIT on (NURSE_UNIT.CODE_VALUE = E.LOC_NURSE_UNIT_CD)
JOIN CODE_VALUE ROOM on (ROOM.CODE_VALUE = E.LOC_ROOM_CD)
JOIN CODE_VALUE BED on (BED.CODE_VALUE = E.LOC_BED_CD)
JOIN CODE_VALUE DISCH_DISPOSITION on (DISCH_DISPOSITION.CODE_VALUE = E.DISCH_DISPOSITION_CD)
JOIN PRSNL ADMITDOC_NAME ON (ADMITDOC_NAME.PERSON_ID = OA.ORDER_PROVIDER_ID)
LEFT JOIN CLINICAL_EVENT HOSP_SUM ON (HOSP_SUM.ENCNTR_ID = E.ENCNTR_ID)
AND HOSP_SUM.EVENT_CD = :p17
AND HOSP_SUM.RESULT_STATUS_CD IN (:p19, :p20, :p21)
AND HOSP_SUM.RECORD_STATUS_CD = 188 -- ACTIVE
AND HOSP_SUM.VALID_UNTIL_DT_TM > cclsql_cnvtdatetimeutc(SYSDATE, 1, 126)
LEFT JOIN PRSNL DCDOC_NAME ON (DCDOC_NAME.PERSON_ID = HOSP_SUM.VERIFIED_PRSNL_ID)
JOIN CODE_VALUE ADMIT_SRC ON (ADMIT_SRC.CODE_VALUE = E.ADMIT_SRC_CD)
JOIN CODE_VALUE ADMIT_TYPE ON (ADMIT_TYPE.CODE_VALUE = E.ADMIT_TYPE_CD)
LEFT JOIN CLINICAL_EVENT ESDP ON (ESDP.ENCNTR_ID = E.ENCNTR_ID)
AND ESDP.EVENT_CD = :p18
AND ESDP.RESULT_STATUS_CD IN (:p19, :p20, :p21)
AND ESDP.RECORD_STATUS_CD = 188 -- ACTIVE
AND ESDP.VALID_UNTIL_DT_TM > cclsql_cnvtdatetimeutc(SYSDATE, 1, 126)
LEFT JOIN (
SELECT O.* FROM ORDERS O WHERE O.ORDER_ID = (
SELECT MAX(O2.ORDER_ID) FROM ORDERS O2 WHERE O2.ENCNTR_ID = E.ENCNTR_ID AND O2.CATALOG_CD = :p22 AND O2.ACTIVE_IND = 1
)) O ON
O.ENCNTR_ID = E.ENCNTR_ID
-- LEFT OUTER JOIN (
-- SELECT * FROM ORDER_ACTION WHERE ORDER_ID = O.ORDER_ID AND ACTION_TYPE_CD IN (:p23, :p24) AND ACTION_SEQUENCE = (
-- SELECT MAX(OA2.ACTION_SEQUENCE)
-- FROM ORDER_ACTION OA2
-- WHERE OA2.ORDER_ID = O.ORDER_ID AND OA2.ACTION_TYPE_CD IN (:p23, :p24)
-- )) OA ON
-- O.ORDER_ID = OA.ORDER_ID
WHERE E.ENCNTR_ID IN (:p0, :p1, :p2, :p3, :p4, :p5, :p6, :p7, :p8, :p9, :p10, :p11, :p12, :p13, :p14, :p15, :p16)
ORDER BY PERSON_ID ASC, REG_DT_TM DESC;
E.ENCNTR_ID on the third line below will not be found, because this subquery is outside the scope of the parent query, so you'll need to join your E table in this subquery. However, since you need the ENCTR_ID specificity in this subquery, you should consider using a CTE (WITH Clause) to prefetch this table.
LEFT JOIN (
SELECT O.* FROM ORDERS O WHERE O.ORDER_ID = (
SELECT MAX(O2.ORDER_ID) FROM ORDERS O2 WHERE O2.ENCNTR_ID = E.ENCNTR_ID AND
O2.CATALOG_CD = :p22 AND O2.ACTIVE_IND = 1
)) O ON
O.ENCNTR_ID = E.ENCNTR_ID
It seems the main thing I was lacking was using a GROUP BY in my subquery. I didn't need to use a derived table at all. Just use a subquery with GROUP BY and duplicate the qualifications in the main join query and the subquery.
SELECT
E.ENCNTR_ID
,E.REASON_FOR_VISIT
-- ,D.DIAGNOSIS_DISPLAY AS DISCHARGE_DX
-- ,D.DIAG_FTDESC AS WORKING_DX
,cclsql_cnvtdatetimeutc(E.REG_DT_TM, 2, 126) as reg_dt_tm
,cclsql_cnvtdatetimeutc(E.DISCH_DT_TM, 2, 126) as disch_dt_tm
,FACILITY.DISPLAY AS FACILITY
,P.PERSON_ID
,P.NAME_FULL_FORMATTED
,cclsql_cnvtdatetimeutc(P.BIRTH_DT_TM, 2, P.BIRTH_TZ) as birth_dt_tm
,MRN.ALIAS AS MRN
,FIN.ALIAS AS FIN
,ENC_TYPE.DISPLAY AS ENCOUNTER_TYPE
,NURSE_UNIT.DISPLAY AS NURSE_UNIT
,ROOM.DISPLAY AS ROOM
,BED.DISPLAY AS BED
-- ,ADMITDOC_NAME.NAME_FULL_FORMATTED AS ADMITDOC_NAME
,DCDOC_NAME.NAME_FULL_FORMATTED AS DCDOC_NAME
,ADMIT_SRC.DISPLAY AS ADMIT_SOURCE
,ADMIT_TYPE.DISPLAY AS ADMIT_TYPE
,ESDP.RESULT_VAL AS ESDP
,DISCH_DISPOSITION.DISPLAY AS DISCH_DISPOSITION
FROM ENCOUNTER E
-- JOIN DISCHARGE D ON (D.ENCNTR_ID = E.ENCNTR_ID)
-- AND D.ACTIVE_IND = 1
-- AND D.END_EFFECTIVE_DT_TM > SYSDATE
JOIN PERSON P ON (P.PERSON_ID = E.PERSON_ID)
JOIN CODE_VALUE ENC_TYPE ON (ENC_TYPE.CODE_VALUE = E.ENCNTR_TYPE_CLASS_CD)
JOIN ENCNTR_ALIAS FIN ON (FIN.ENCNTR_ID = E.ENCNTR_ID)
AND FIN.ENCNTR_ALIAS_TYPE_CD = 1077 -- FIN CODE
AND FIN.ACTIVE_IND = 1
AND FIN.ACTIVE_STATUS_CD = 188
JOIN ENCNTR_ALIAS MRN ON (MRN.ENCNTR_ID = E.ENCNTR_ID)
AND MRN.ENCNTR_ALIAS_TYPE_CD = 1079 -- MRN CODE
AND MRN.ACTIVE_IND = 1
AND MRN.ACTIVE_STATUS_CD = 188
JOIN CODE_VALUE FACILITY on (FACILITY.CODE_VALUE = E.LOC_FACILITY_CD)
JOIN CODE_VALUE NURSE_UNIT on (NURSE_UNIT.CODE_VALUE = E.LOC_NURSE_UNIT_CD)
JOIN CODE_VALUE ROOM on (ROOM.CODE_VALUE = E.LOC_ROOM_CD)
JOIN CODE_VALUE BED on (BED.CODE_VALUE = E.LOC_BED_CD)
JOIN CODE_VALUE DISCH_DISPOSITION on (DISCH_DISPOSITION.CODE_VALUE = E.DISCH_DISPOSITION_CD)
LEFT JOIN ORDERS O ON
O.ENCNTR_ID = E.ENCNTR_ID AND O.CATALOG_CD = :p22 AND O.ACTIVE_IND = 1 AND O.ORDER_ID IN (
SELECT MAX(O2.ORDER_ID) FROM ORDERS O2 WHERE O2.ENCNTR_ID = E.ENCNTR_ID AND O2.CATALOG_CD = :p22 AND O2.ACTIVE_IND = 1 GROUP BY O2.ENCNTR_ID
)
LEFT JOIN ORDER_ACTION OA ON
OA.ORDER_ID = O.ORDER_ID AND OA.ACTION_TYPE_CD IN (:p23, :p24) AND OA.ACTION_SEQUENCE IN (
SELECT MAX(OA2.ACTION_SEQUENCE) FROM ORDER_ACTION OA2 WHERE OA2.ORDER_ID = O.ORDER_ID AND OA2.ACTION_TYPE_CD IN (:p23, :p24) GROUP BY OA2.ORDER_ID
)
LEFT JOIN PRSNL ADMITDOC_NAME ON (ADMITDOC_NAME.PERSON_ID = OA.ORDER_PROVIDER_ID)
LEFT JOIN CLINICAL_EVENT HOSP_SUM ON (HOSP_SUM.ENCNTR_ID = E.ENCNTR_ID)
AND HOSP_SUM.EVENT_CD = :p17
AND HOSP_SUM.RESULT_STATUS_CD IN (:p19, :p20, :p21)
AND HOSP_SUM.RECORD_STATUS_CD = 188 -- ACTIVE
AND HOSP_SUM.VALID_UNTIL_DT_TM > cclsql_cnvtdatetimeutc(SYSDATE, 1, 126)
LEFT JOIN PRSNL DCDOC_NAME ON (DCDOC_NAME.PERSON_ID = HOSP_SUM.VERIFIED_PRSNL_ID)
JOIN CODE_VALUE ADMIT_SRC ON (ADMIT_SRC.CODE_VALUE = E.ADMIT_SRC_CD)
JOIN CODE_VALUE ADMIT_TYPE ON (ADMIT_TYPE.CODE_VALUE = E.ADMIT_TYPE_CD)
LEFT JOIN CLINICAL_EVENT ESDP ON (ESDP.ENCNTR_ID = E.ENCNTR_ID)
AND ESDP.EVENT_CD = :p18
AND ESDP.RESULT_STATUS_CD IN (:p19, :p20, :p21)
AND ESDP.RECORD_STATUS_CD = 188 -- ACTIVE
AND ESDP.VALID_UNTIL_DT_TM > cclsql_cnvtdatetimeutc(SYSDATE, 1, 126)
WHERE E.ENCNTR_ID IN (:p0, :p1, :p2, :p3, :p4, :p5, :p6, :p7, :p8, :p9, :p10, :p11, :p12, :p13, :p14, :p15, :p16)
ORDER BY PERSON_ID ASC, REG_DT_TM DESC

Single-row subquery returns more than one row - Case statement

My following code returns the error stated in the title, however the error does not show when the case statement is ran by itself.
I've tried to dismantle the case statement, however this isn't my query but IS being used elsewhere, i'm wondering how they manage to get it to return rows in its current state.
SELECT DISTINCT V55."INPUTSPECNAME",
V55."FKMATERIAL",
V55."INPUTQUANTITYVALUE",
B.ABBREVIATION,
(CASE
WHEN z.COST IS NULL
THEN (SELECT DISTINCT (CASE
WHEN MatOut_D.PERVALUEQUANTITY > 0 THEN
ROUND(MatOut_D.PRICE /
MatOut_D.PERVALUEQUANTITY /
10 /
MatOut_E.USDCONVERSIONFACTOR *
C.USDCONVERSIONFACTOR, 5)
ELSE 0
END)
FROM V55_FORMULATIONJOINMATOUTPUT MatOut_B,
V55_FORMULATIONINPUTOUTPUT MatOut_C,
THEORETICALCOSTS MatOut_D,
COMMONCURRENCIES MatOut_E,
UOMML MatOut_F
WHERE MatOut_B.FKREFERENCEDMATERIAL = V55.FKMATERIAL
AND MatOut_B.FKOWNER = MatOut_C.FKOWNER
AND MatOut_C.FORMULATIONOUTPUTPKID = MatOut_D.FKPARENT
AND MatOut_D.FKCURRENCY = MatOut_E.PKID
AND MatOut_D.FKPERVALUEUOM = MatOut_F.FKUOM
AND MatOut_F.LANGID = 0)
ELSE ROUND(z.COST*100/D.USDCONVERSIONFACTOR*C.USDCONVERSIONFACTOR,5)
END) AS COST_100G
FROM V55_FORMULATIONINPUTOUTPUT V55
INNER JOIN UOM A
on V55.FKINPUTUOM = A.PKID
INNER JOIN UOMML B
on a.pkid = B.FKUOM
INNER JOIN DWBSpecificationRoots dwbRoot
on dwbRoot.fkOwner = V55.FKOWNER
INNER JOIN dwbSpecifications dwbSpec
ON dwbSpec.fkWorkingVersionParent = dwbRoot.pkid
LEFT OUTER JOIN specLegacySpecJoin y
on dwbSpec.fkdisplayedlegacyprofile = y.fklegacyprofileid
and y.fkspecid = V55.fkMaterial
LEFT OUTER join COSTITEMS z
on z.equivalent = y.equivalent
and z.fklegacyprofile = dwbSpec.fkdisplayedlegacyprofile
and z.FKSCRMENTITY = dwbSpec.FKSCRMSUPPLIERBASE
and z.COSTTYPE = dwbSpec.COSTTYPE
LEFT OUTER JOIN COMMONCURRENCIES C
ON C.PKID = dwbSpec.FKCURRENCY
LEFT OUTER JOIN COMMONCURRENCIES D
ON D.PKID = Z.FKCURRENCY
The problem is that the subquery in your CASE statement is returning multiple rows in some situations and as has been stated in the question's comments that's a no-no.
I suggest that you pull the subquery out of the CASE statement and make it a Common Table Expression, then join it into the query as you would any other table:
WITH cteSubexpr AS (SELECT DISTINCT MatOut_B.FKREFERENCEDMATERIAL,
(CASE
WHEN MatOut_D.PERVALUEQUANTITY > 0 THEN
ROUND(MatOut_D.PRICE /
MatOut_D.PERVALUEQUANTITY /
10 /
MatOut_E.USDCONVERSIONFACTOR *
C.USDCONVERSIONFACTOR, 5)
ELSE 0
END) AS CALC_QTY
FROM V55_FORMULATIONJOINMATOUTPUT MatOut_B
INNER JOIN V55_FORMULATIONINPUTOUTPUT MatOut_C
ON MatOut_C.FKOWNER = MatOut_B.FKOWNER
INNER JOIN THEORETICALCOSTS MatOut_D
ON MatOut_D.FKPARENT = MatOut_C.FORMULATIONOUTPUTPKID
INNER JOIN COMMONCURRENCIES MatOut_E
ON MatOut_E.PKID = MatOut_D.FKCURRENCY
INNER JOIN UOMML MatOut_F
ON MatOut_F.FKUOM = MatOut_D.FKPERVALUEUOM
WHERE MatOut_F.LANGID = 0)
SELECT DISTINCT V55.INPUTSPECNAME,
V55.FKMATERIAL,
V55.INPUTQUANTITYVALUE,
B.ABBREVIATION,
(CASE
WHEN z.COST IS NULL
THEN cs.CALC_QTY
ELSE ROUND(z.COST * 100 / D.USDCONVERSIONFACTOR * C.USDCONVERSIONFACTOR, 5)
END) AS COST_100G
FROM V55_FORMULATIONINPUTOUTPUT V55
INNER JOIN cteSubexpr cs
ON cs.FKREFERENCEDMATERIAL = V55.FKMATERIAL
INNER JOIN UOM A
on V55.FKINPUTUOM = A.PKID
INNER JOIN UOMML B
on a.pkid = B.FKUOM
INNER JOIN DWBSpecificationRoots dwbRoot
on dwbRoot.fkOwner = V55.FKOWNER
INNER JOIN dwbSpecifications dwbSpec
ON dwbSpec.fkWorkingVersionParent = dwbRoot.pkid
LEFT OUTER JOIN specLegacySpecJoin y
on dwbSpec.fkdisplayedlegacyprofile = y.fklegacyprofileid
and y.fkspecid = V55.fkMaterial
LEFT OUTER join COSTITEMS z
on z.equivalent = y.equivalent
and z.fklegacyprofile = dwbSpec.fkdisplayedlegacyprofile
and z.FKSCRMENTITY = dwbSpec.FKSCRMSUPPLIERBASE
and z.COSTTYPE = dwbSpec.COSTTYPE
LEFT OUTER JOIN COMMONCURRENCIES C
ON C.PKID = dwbSpec.FKCURRENCY
LEFT OUTER JOIN COMMONCURRENCIES D
ON D.PKID = Z.FKCURRENCY
Best of luck.

How can I use the group by Clause in a subquery

I just need to select one more field in my query that is the date... but it's a subquery and i'm using a count field... and because of it i need to use the GROUP BY Clause... But i can't group by my subquery and the query is returning errors...
SELECT
X.NROF,
Z.NMGUERFORN,
C.CDCOMPRADO,
C.CDCOORDENA,
E.CDFUP,
count(*) AS ocorrencias
--(select TOP 1 DTPROGENTR from CMPENL0 C (NOLOCK) where X.NRPEDICOMP = C.NRPEDICOMP AND X.NRITEMPECO = C.NRITEMPECO) AS DTPROGENTR
FROM CMPCIL0 X (NOLOCK)
inner join CMPCCL0 Y (NOLOCK) on X.NRPEDICOMP = Y.NRPEDICOMP
inner join CMFRNL0 Z (NOLOCK) on Y.CDFORNECED1 = Z.CDFORNECED1
inner join CMSCPL0 M (NOLOCK) on X.NRSOLICOMP = M.NRSOLICOMP AND X.NRITEMSC = M.NRITEMSC
inner join CMPENL0 N (NOLOCK) on X.NRPEDICOMP = N.NRPEDICOMP AND X.NRITEMPECO = N.NRITEMPECO
inner join CMMATL0 A (NOLOCK) on X.CDMATERIAL = A.CDMATERIAL
inner join cmcomL0 c (NOLOCK) on c.cdcomprado = y.cdcomprado
LEFT JOIN AMCSPL0 D (NOLOCK) ON D.SCPE_NRSOLICOMP = X.NRSOLICOMP AND D.SCPE_NRITEMSC=X.NRITEMSC
LEFT JOIN CMFUPL0 E (NOLOCK) ON E.CDFORNECED1 = Z.CDFORNECED1
LEFT JOIN CMPFIL0 H ON Z.CDFORNECED1 = H.CDFORNECED1 AND X.NRIDENTIFI = H.NRIDENTIFI and H.DTVALIDADE > Y.DTEFETPECO
LEFT JOIN CMPENL0 F ON (X.NRPEDICOMP = F.NRPEDICOMP AND X.NRITEMPECO = F.NRITEMPECO)
WHERE X.CDSTATUS = 'P' and X.NROF <> 0
group by X.NROF,Z.NMGUERFORN,C.CDCOMPRADO,C.CDCOORDENA,E.CDFUP--,DTPROGENTR
order by 6 desc
The commented parts are the code im trying to include to select the field, but it is giving me errors..
The problem is that you use aliases in your where clause of select sub-query. Aliases cannot be referenced on the same level in the query. You should use full qualified names and the sub-query should look something like that:
(select TOP 1 DTPROGENTR from CMPENL0 C (NOLOCK) where X.NRPEDICOMP = CMPENL0.NRPEDICOMP AND X.NRITEMPECO = CMPENL0.NRITEMPECO) AS DTPROGENTR
If your sql-server supports common table expressions you can try that:
;WITH cte AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY NRPEDICOMP, NRITEMPECO ORDER BY NRPEDICOMP) row_num
,DTPROGENTR
,NRPEDICOMP
,NRITEMPECO
FROM CMPENL0 (NOLOCK)
)
SELECT
X.NROF,
Z.NMGUERFORN,
C.CDCOMPRADO,
C.CDCOORDENA,
E.CDFUP,
count(*) AS ocorrencias
cte.DTPROGENTR
FROM CMPCIL0 X (NOLOCK)
inner join CMPCCL0 Y (NOLOCK) on X.NRPEDICOMP = Y.NRPEDICOMP
inner join CMFRNL0 Z (NOLOCK) on Y.CDFORNECED1 = Z.CDFORNECED1
inner join CMSCPL0 M (NOLOCK) on X.NRSOLICOMP = M.NRSOLICOMP AND X.NRITEMSC = M.NRITEMSC
inner join CMPENL0 N (NOLOCK) on X.NRPEDICOMP = N.NRPEDICOMP AND X.NRITEMPECO = N.NRITEMPECO
inner join CMMATL0 A (NOLOCK) on X.CDMATERIAL = A.CDMATERIAL
inner join cmcomL0 c (NOLOCK) on c.cdcomprado = y.cdcomprado
LEFT JOIN AMCSPL0 D (NOLOCK) ON D.SCPE_NRSOLICOMP = X.NRSOLICOMP AND D.SCPE_NRITEMSC=X.NRITEMSC
LEFT JOIN CMFUPL0 E (NOLOCK) ON E.CDFORNECED1 = Z.CDFORNECED1
LEFT JOIN CMPFIL0 H ON Z.CDFORNECED1 = H.CDFORNECED1 AND X.NRIDENTIFI = H.NRIDENTIFI and H.DTVALIDADE > Y.DTEFETPECO
LEFT JOIN CMPENL0 F ON X.NRPEDICOMP = F.NRPEDICOMP AND X.NRITEMPECO = F.NRITEMPECO
LEFT JOIN cte ON X.NRPEDICOMP = cte.NRPEDICOMP AND X.NRITEMPECO = cte.NRITEMPECO AND cte.row_num = 1
WHERE X.CDSTATUS = 'P' and X.NROF <> 0
group by X.NROF,Z.NMGUERFORN,C.CDCOMPRADO,C.CDCOORDENA,E.CDFUP, cte.DTPROGENTR
order by 6 desc

How to convert correlated sub query containing duplicate table to non-correlated one?

I have to convert the correlated sub-query to non-correlated sub-query cuz of performance issues .
like that :
The correlated sub-query :(So slow ) returns 4000 row
SELECT a.personid,a.name,b.conid,d.condat,e.connam
FROM main_empr a INNER JOIN coninr b
ON a.personid = b.personid AND a.calc_year = b.calc_year
INNER JOIN mainconinr c
ON b.conid = c.conid
INNER JOIN coninr d
ON a.personid = d.personid AND a.calc_year = d.calc_year
INNER JOIN mainconinr e
ON d.conid = e.conid
WHERE c.active_flag = 1 and c.endreward_flag = 1
AND d.condat = (SELECT MIN(bb.condat) FROM coninr bb WHERE bb.personid = b.personid AND bb.calc_year = b.calc_year AND ((bb.conid > 0 AND bb.conid < 4 ) OR (bb.conid IN(16,6) )) )
AND b.condat = (SELECT MAX(bb.condat) FROM coninr bb WHERE bb.personid = b.personid AND bb.calc_year = b.calc_year AND ((bb.conid > 0 AND bb.conid < 4 ) OR (bb.conid IN(16,6) )) )
AND ( 0 = ( SELECT COUNT(*) FROM servmain x WHERE x.personid = a.personid AND x.calc_year = a.calc_year )
OR b.condat > ( SELECT MAX(x.serv_date) FROM servmain x WHERE x.personid = a.personid AND x.calc_year = a.calc_year ) )
AND a.calc_year = 2018
The non-correlated query :returns about 12300 rows!!
SELECT a.personid,a.name,b.conid,d.condat,e.connam
FROM main_empr a INNER JOIN
coninr b
ON a.personid = b.personid AND a.calc_year = b.calc_year
INNER JOIN mainconinr c
ON b.conid = c.conid
INNER JOIN coninr d
ON a.personid = d.personid AND a.calc_year = d.calc_year
INNER JOIN mainconinr e ON d.conid = e.conid
INNER JOIN
(SELECT MAX(bb.condat) AS condat ,bb.personid,bb.calc_year ,bb.conid
FROM coninr bb
GROUP BY bb.personid,bb.calc_year,bb.conid
)Max_cont
ON Max_cont.personid = b.personid AND Max_cont.calc_year = b.calc_year AND Max_cont.condat = b.condat AND ((Max_cont.conid > 0 AND Max_cont.conid < 4 ) OR (Max_cont.conid IN(16,6) ))
INNER JOIN
(SELECT MIN(dd.condat) AS condat ,dd.personid,dd.calc_year,dd.conid
FROM coninr dd GROUP BY dd.personid,dd.calc_year,dd.conid
)Min_cont
ON Min_cont.personid = d.personid AND Min_cont.calc_year = d.calc_year AND Min_cont.condat = d.condat AND ((Min_cont.conid > 0 AND Min_cont.conid < 4 ) OR (Min_cont.conid IN(16,6) ))
WHERE c.active_flag = 1 and c.endreward_flag = 1
AND ( 0 = ( SELECT COUNT(*) FROM servmain x WHERE x.personid = a.personid AND x.calc_year = a.calc_year )
OR b.condat > ( SELECT MAX(x.serv_date) FROM servmain x WHERE x.personid = a.personid AND x.calc_year = a.calc_year ) )
AND a.calc_year = 2018
The problem is :
I use the coninr table twice to get the last and the first contract date in the same row .
It works fine in the first query but it was so slow because of the correlated sub-query,but in the second query it brings more than one row for the same person one of them for the first contract date and the other for the last one !!
How to fix this problem ?
This looks reasonable, but I've no way to know how it'll perform:
SELECT a.personid,a.name,b.conid,d.condat,e.connam
FROM main_empr a INNER JOIN coninr b
ON a.personid = b.personid AND a.calc_year = b.calc_year
INNER JOIN mainconinr c
ON b.conid = c.conid
INNER JOIN coninr d
ON a.personid = d.personid AND a.calc_year = d.calc_year
INNER JOIN mainconinr e
ON d.conid = e.conid
inner join
(
SELECT bb.personid, bb.calc_year, bb.conid, MIN(bb.condat) MinDate, MAX(bb.condat) MaxDate
FROM coninr bb WHERE
where (bb.conid > 0 and bb.conid < 4) or (bb.conid in (6, 16))
group by bb.personid, bb.calc_year, bb.conid
) zz on d.concat = zz.MinDate and b.condat = zz.MaxDate and b.personid = zz.personid and b.calc_year = zz.calc_year
left outer join
(
select s.personid, s.calc_year, max(s.serv_date) MaxServDate
from servmain s
group by s.personid, s.calc_year
) s on a.personid = s.personid and a.calc_year = s.calc_year
WHERE c.active_flag = 1 and c.endreward_flag = 1
and (s.MaxServDate is null or b.condat ? s.MaxServDate
AND a.calc_year = 2018
You don't need two queries for table coninr, you can get min and max in the same query with the group by. Also, for ServMain, doing a left outer join and putting in the where that either it's null (equivalent to count(*) = 0) or is less than b.condat takes care of that.

Sql : How to calculate table values using formula

Here is original Query :, it generates o/p with two columns name (label, count) :
label count
Fails 1
Pass 3
and here is query I wrote which generates above data
select r.pname as resolution
,lb.label
,count(r.pname) as occurences
from issuelink
inner join jiraissue p on issuelink.source = p.id
inner join jiraissue c on issuelink.destination = c.id
inner join issuelinktype t on issuelink.linktype = t.id
inner join resolution r on c.resolution = r.id
inner join issuestatus istat on p.issuestatus = istat.sequence
inner join label lb on c.id = lb.issue
where t.linkname = 'jira_subtask_link'
and p.pkey in (#pkey)
and c.issuetype in ('13')
and r.pname not in ('Fails Smoke Test - General Failure', 'Fails Smoke Test - New Firmware Available')
and label in ('SmokeTest', 'fullcert', 'bfv', 'papercert')
group by r.pname;
As per your suggestion I tried using cross function, however its throwing an error of "please check syntax":
select 100.0 * fail.cnt / (fail.cnt + pass.cnt) as c
from (
select r.pname as label
, count(r.pname) as cnt
from issuelink
inner join jiraissue p on issuelink.source = p.id
inner join jiraissue c on issuelink.destination = c.id
inner join issuelinktype t on issuelink.linktype = t.id
inner join resolution r on c.resolution = r.id
inner join issuestatus istat on p.issuestatus = istat.sequence
inner join label lb on c.id = lb.issue
where t.linkname = 'jira_subtask_link'
and p.pkey in ('SRPDTVTPV-3')
and c.issuetype in ('13')
and r.pname not in ('Fails Smoke Test - General Failure', 'Fails Smoke Test - New Firmware Available')
and label in ('SmokeTest', 'fullcert', 'bfv', 'papercert')
group by r.pname
) as fail
cross join
(
select r.pname as label
, count(r.pname) as cnt
from issuelink
inner join jiraissue p on issuelink.source = p.id
inner join jiraissue c on issuelink.destination = c.id
inner join issuelinktype t on issuelink.linktype = t.id
inner join resolution r on c.resolution = r.id
inner join issuestatus istat on p.issuestatus = istat.sequence
inner join label lb on c.id = lb.issue
where t.linkname = 'jira_subtask_link'
and p.pkey in ('SRPDTVTPV-3')
and c.issuetype in ('13')
and r.pname not in ('Fails Smoke Test - General Failure', 'Fails Smoke Test - New Firmware Available')
and label in ('SmokeTest', 'fullcert', 'bfv', 'papercert')
group by r.pname
) as pass
where fail.label = 'Fails Certification'
and pass.label = 'Passes Certification'
Here's one way using a cross join:
select 100.0 * a.count / (a.count + b.count) as c
from YourQuery a
cross join
YourQuery b
where a.label = 'a'
and b.label = 'b'
Here's another approach using aggregates, a bit more tricky but only uses YourQuery once:
select 100.0 * cnt_a / (cnt_a + cnt_b) as c
from (
select max(case when label = 'a' then count end) as cnt_a
, max(case when label = 'b' then count end) as cnt_b
from YourQuery
) as SubQueryAlias