several select counts in select could be enhanced? - sql

I have the below query , If the table data grows and contained millions of record , would it cause performance issue ? can it be enhanced in a way I dont run select count() in the select several time ? I already added index on the 6 columns.
I know the join is bad I am already enhancing the query
SELECT
P.CID,
P.CB,
(SELECT COUNT(1)
FROM EED_TABLE F
WHERE F.ID = P.ID
AND F.BC = P.BC
AND F.PCD = P.PCD
AND F.CID = P.CID
AND F.BRC = P.BRC
AND F.ST = 'F') ST_F,
(SELECT COUNT(1)
FROM EED_TABLE N
WHERE N.ID = P.ID
AND N.BC = P.BC
AND N.PCD = P.PCD
AND N.COMP_CODE = P.COMP_CODE
AND N.BRC = P.BRC
AND N.ST = 'N') ST_N,
(SELECT COUNT(1)
FROM EED_TABLE A
WHERE A.ID = P.ID
AND A.BC = P.BC
AND A.PCD = P.PCD
AND A.CID = P.CID
AND F.BRC = P.BRC
AND A.ST = 'A') ST_A
FROM EED_TABLE P ,EDD_DEF D
WHERE P.PCD = D.PCD
AND P.BC= D.BC
AND P.CD= 1
AND P.ID = 1
AND P.BC= 22
AND P.PCD = 31

I always prefer to go for JOIN instead of having more select statements, this is how I would do it, not knowing your data of course so maybe it won't work, but give it a shot and let me know of results and speed
select
p.cid, p.cb, SUM(case when f.id is not null then 1 else 0 end) st_f,
, SUM(case when a.id is not null then 1 else 0 end) st_a
, SUM(case when n.id is not null then 1 else 0 end) st_n
from eed_table p
join edd_def d on p.pcd = d.pcd and p.bc = d.bc
left join eed_table f on f.id = p.id and f.bc = p.bc
and f.pcd = p.pcd and f.cid = p.cid
and f.brc = p.brc and f.st = 'f'
left join eed_table a on p.id = a.id and p.bc = a.bc
and p.pcd = a.pcd and p.cid = a.cid
and p.brc = a.brc and a.st = 'a'
left join eed_table n on n.id = p.id and n.bc = p.bc
and n.pcd = p.pcd and n.comp_code = p.comp_code
and n.brc = p.brc and n.st = 'n'
where p.cd = 1 and p.id = 1 and p.bc = 22 and p.pcd = 31
group by p.cid, p.cb

Seems that your query can be rewritten with window functions as:
SELECT
DISTINCT P.CID, P.CB
, SUM(CASE WHEN P.ST = 'F' THEN 1 ELSE 0 END) OVER (PARTITION BY P.ID, P.BC, P.PCD, P.CID, P.BRC) ST_F
, SUM(CASE WHEN P.ST = 'N' THEN 1 ELSE 0 END) OVER (PARTITION BY P.ID, P.BC, P.PCD, P.COMP_CODE, P.BRC) ST_N
, SUM(CASE WHEN P.ST = 'A' THEN 1 ELSE 0 END) OVER (PARTITION BY P.ID, P.BC, P.PCD, P.CID, P.BRC) ST_A
FROM
EED_TABLE P
WHERE
P.CD = 1
AND P.ID = 1
AND P.BC = 22
AND P.PCD = 31
AND EXISTS (SELECT 1 FROM EDD_DEF D WHERE P.PCD = D.PCD AND P.BC= D.BC)

Related

Why does the subquery throw errors in a group by query?

Ok, I will try a 2nd attempt because the first one was not that intelligent
My Query:
SELECT distinct kg.datum,
sum(case when leis.code = 'Oph3001' then leis.anzahl END) as leis3001,
sum(case when leis.code = 'Oph3003' then leis.anzahl END) as leis3003,
(select nvl((select to_date(KG2.KURZTEXT, 'dd.mm.yyyy')from kg_eintraege kg2 where kg2.kgtitel_nr = 1003350007 and kg.fall_nr = kg2.fall_nr and kg.patient_nr = kg2.patient_nr and kg.kg_id = kg2.kontext),'') from dual) as real_datum
FROM kg_eintraege kg
INNER JOIN aufenthalte a
ON kg.patient_nr = a.patient_nr
and kg.fall_nr = a.fall_nr
INNER JOIN MF_LEIS_DIAG_OP_MD leis
on leis.aufenthalte_nr = a.nr
group by kg.datum, kg.kg_id
order by /*real_datum*/ kg.datum desc
The following subquery is causing the problem:
(select nvl((select to_date(KG2.KURZTEXT, 'dd.mm.yyyy')from kg_eintraege kg2 where kg2.kgtitel_nr = 1003350007 and kg.fall_nr = kg2.fall_nr and kg.patient_nr = kg2.patient_nr and kg.kg_id = kg2.kontext),'') from dual)
Puting it into the group by expression throws the ORA-22818 error ("subquery not allowed here").
Not puting it throws the ORA-00979 error ("not a group by expression").
Can someone help me?
You could use an outer join instead; something like:
SELECT distinct kg.datum,
sum(case when leis.code = 'Oph3001' then leis.anzahl END) as leis3001,
sum(case when leis.code = 'Oph3003' then leis.anzahl END) as leis3003,
to_date(KG2.KURZTEXT, 'dd.mm.yyyy') as real_datum
FROM kg_eintraege kg
INNER JOIN aufenthalte a
ON kg.patient_nr = a.patient_nr
and kg.fall_nr = a.fall_nr
INNER JOIN MF_LEIS_DIAG_OP_MD leis
on leis.aufenthalte_nr = a.nr
LEFT OUTER JOIN kg_eintraege kg2
on kg2.kgtitel_nr = 1003350007
and kg.fall_nr = kg2.fall_nr
and kg.patient_nr = kg2.patient_nr
and kg.kg_id = kg2.kontext
group by kg.datum, kg.kg_id, to_date(KG2.KURZTEXT, 'dd.mm.yyyy')
order by /*real_datum*/ kg.datum desc
you can use a subquery
select datum,
sum(case when code = 'Oph3001' then anzahl END) as leis3001,
sum(case when code = 'Oph3003' then anzahl END) as leis3003,
real_datum
from (
SELECT distinct kg.datum,
leis.code,
leis.anzahl,
(select nvl((select to_date(KG2.KURZTEXT, 'dd.mm.yyyy')from kg_eintraege kg2 where kg2.kgtitel_nr = 1003350007 and kg.fall_nr = kg2.fall_nr and kg.patient_nr = kg2.patient_nr and kg.kg_id = kg2.kontext),'') from dual) as real_datum
FROM kg_eintraege kg
INNER JOIN aufenthalte a ON kg.patient_nr = a.patient_nr
and kg.fall_nr = a.fall_nr
INNER JOIN MF_LEIS_DIAG_OP_MD leis on leis.aufenthalte_nr = a.nr
)
group by datum, kg_id, real_datum
order by /*real_datum*/ kg.datum desc

A new row for each record

I would like the results to produce a new row in each instance where a condition is met. I'm using a CASE statement but this isn't the way to go since once the first condition is met it stops evaluating the field.
SELECT
Reviews.ReviewID,
CASE
WHEN Score_CorrectID = 0 THEN 'Correct ID Right Party Authentication'
WHEN Score_ProperlyIdentified = 0 THEN 'PCA Properly Identified Itself'
WHEN Score_MiniMiranda = 0 THEN 'Mini-Miranda'
END AS [Error Type]
FROM Reviews INNER JOIN PCAs ON Reviews.PCAID = PCAs.PCAID LEFT JOIN
PCARebuttal ON Reviews.ReviewID = PCARebuttal.ReviewID
WHERE
(Score_CorrectID = 0 OR Score_ProperlyIdentified = 0 OR Score_MiniMiranda =
0)
This produces this:
I would like this:
Use apply:
SELECT r.ReviewID, v.error_type
FROM Reviews r INNER JOIN
PCAs
ON r.PCAID = PCAs.PCAID LEFT JOIN
PCARebuttal pr
ON r.ReviewID = pr.ReviewID OUTER APPLY
(SELECT *
FROM (VALUES (Score_CorrectID, 'Correct ID Right Party Authentication'),
(Score_ProperlyIdentified, 'PCA Properly Identified Itself'),
(Score_MiniMiranda, 'Mini-Miranda')
) v(score, error_type)
WHERE score = 0
) v
WHERE (Score_CorrectID = 0 OR Score_ProperlyIdentified = 0 OR Score_MiniMiranda = 0);
That said, I would probably just concatenate the values into a single column:
SELECT r.ReviewID,
( (CASE WHEN Score_CorrectID = 0 THEN 'Correct ID Right Party Authentication; ' ELSE '' END) +
(CASE WHEN Score_ProperlyIdentified = 0 THEN 'PCA Properly Identified Itself; ' ELSE '' END) +
(CASE WHEN Score_MiniMiranda = 0 THEN 'Mini-Miranda;' ELSE '' END)
) as error_types
FROM Reviews r INNER JOIN
PCAs
ON r.PCAID = PCAs.PCAID LEFT JOIN
PCARebuttal pr
ON r.ReviewID = pr.ReviewID OUTER APPLY
(SELECT *
FROM (VALUES ()
) v(score, error_type)
WHERE score = 0
) v
WHERE (Score_CorrectID = 0 OR Score_ProperlyIdentified = 0 OR Score_MiniMiranda = 0);
Instead of using case, you can use union all instead:
SELECT
Reviews.ReviewID,
'Correct ID Right Party Authentication' AS [Error Type]
FROM Reviews
INNER JOIN PCAs ON Reviews.PCAID = PCAs.PCAID
LEFT JOIN PCARebuttal ON Reviews.ReviewID = PCARebuttal.ReviewID
WHERE Score_CorrectID = 0
UNION ALL
SELECT
Reviews.ReviewID,
'PCA Properly Identified Itself' AS [Error Type]
FROM Reviews
INNER JOIN PCAs ON Reviews.PCAID = PCAs.PCAID
LEFT JOIN PCARebuttal ON Reviews.ReviewID = PCARebuttal.ReviewID
WHERE Score_ProperlyIdentified = 0
UNION ALL
SELECT
Reviews.ReviewID,
'Mini-Miranda' AS [Error Type]
FROM Reviews
INNER JOIN PCAs ON Reviews.PCAID = PCAs.PCAID
LEFT JOIN PCARebuttal ON Reviews.ReviewID = PCARebuttal.ReviewID
WHERE Score_MiniMiranda = 0

ORA-01799: a column may not be outer-joined to a subquery

hi good people please find the code below is running in db2 but fails in oracle.
select * from
(select distinct e.time_stamp,e.applicationid, e.processname,
e.stage, e.initiatingsource, e.status, e.start_time, i.consultant,
g.cifnumber, g.applicantfirstname, g.applicantlastname,
case when e.branch is not null
then e.branch
else case when g.branch is not null
then g.branch
else i.branch
end
end as branch
from (select c.time_stamp, b.applicationid, b.processname,
b.stage, b.branch, b.initiatingsource,
case when d.status is null
then c.status
else d.status
end as status,
c.time_stamp as START_TIME,
case when d.time_stamp is not null
then d.time_stamp
else current_timestamp
ens as END_TIME
from (select distinct f.applicationid, f.branch, f.initiatingsource, f.processname,
case when f.stage in ('START''END')
then 'APPLICATION'
else f.stage, f.stagecounter
from processmetric f) b
left join processmetric c on b.applicationid = c.applicationid and b.processname = c.processname and (b.stage = c.stage or (b.stage = 'APPLICATION' and c.stage = 'START')) and b.stagecounter = c.stagecounter and c.phase = 'START'
left join processmetric d on b.applicationid = d.applicationid and b.processname = d.processname and (b.stage = d.stage or (b.stage = 'APPLICATION' and d.stage = 'END')) and b.stagecounter = d.stagecounter and d.phase ='END')e
left join applicationcustomerdata g on g.applicationid = e.applicationid
and g.time_stamp in (select max(x.time_stamp)
from applicationcustomerdata x
where x.applicationid = g.applicationid
)
left join applicationdata i on i.applicationid = e.applicationid
and i.time_stamp in (select max(z.time_stamp)
from applicationdata z
where z.applicationid = i.applicationid
)
order by e.start_time
) a
where a.start_time is not null and a.stage not in ('APPLICATION') and a.status not in ('COMPLETE' , 'COMPLETED' , 'CANCEL', 'FRAUD' , 'DECLINE') and a.stage = 'VERIFICATION';
Oracle don't allow to make outer join with subquery. Following 2 joins are problematic ones:
left join applicationcustomerdata g on g.applicationid = e.applicationid
and g.time_stamp in (select max(x.time_stamp)
from applicationcustomerdata x
where x.applicationid = g.applicationid
)
left join applicationdata i on i.applicationid = e.applicationid
and i.time_stamp in (select max(z.time_stamp)
from applicationdata z
where z.applicationid = i.applicationid
)
You need to rewrite statement (if you need this all in one SQL) or write some PL/SQL loops through data.

Syntax error on request optimisation

I'm trying to optimize a SQL query but I face a weird issue.
Here is my optimized request :
SELECT proj.ProjetId AS ProjetId,
SUM (CASE WHEN modTrans.Code != 'FoO' THEN 1 ELSE 0 END) AS VAL1,
SUM(CASE WHEN modTrans.Code = 'Foo' THEN 1 ELSE 0 END) AS VAL2
FROM Projet.Projet proj
INNER JOIN Workflow.PointControle ptCont
ON ptCont.ProjetId = proj.ProjetId
INNER JOIN Workflow.PointControleModele ptContMod
ON ptContMod.PointControleModeleId = ptCont.PointControleModeleId
INNER JOIN Commande.CommandeTAC cdeTAC
ON cdeTAC.ProjetId = proj.ProjetId
INNER JOIN Commande.CommandeTACCatalogue cdeTACCat
ON cdeTACCat.CommandeTACId = cdeTAC.CommandeTACId
INNER JOIN Fournisseur.Fournisseur four
ON four.FournisseurId = cdeTACCat.FournisseurId
INNER JOIN Fournisseur.ModeTransmission modTrans
ON modTrans.ModeTransmissionId = four.ModeTransmissionId
WHERE ptContMod.PointControleModeleCode = 'FFooooooooo'
AND ptCont.Etat = 'Foooooo'
AND proj.DateLivraison IS NOT NULL
AND [proj].[DateLivraison] <= DATEADD(DAY, 14, GETDATE())
GROUP BY proj.ProjetId
HAVING COUNT(VAL1) > 0 AND COUNT(VAL2) = 0
I got this error :
Column name invalid : 'VAL1' Column name invalid : 'VAL2'
The error is in the HAVING section.
After reading this documentation I dont undestand why there is an error because I respect the syntax : http://www.w3schools.com/sql/sql_having.asp
You can find the unoptimized complete request here :
BEGIN
WITH Trans(VAL1, VAL2, projetId) AS
(
SELECT SUM (CASE WHEN modTrans.Code != 'Foo' THEN 1 ELSE 0 END) AS NbNonSALM
, SUM(CASE WHEN modTrans.Code = 'Foo' THEN 1 ELSE 0 END) AS NbSALM
, proj.ProjetId AS projetId
FROM Projet.Projet proj
INNER JOIN Workflow.PointControle ptCont
ON ptCont.ProjetId = proj.ProjetId
INNER JOIN Workflow.PointControleModele ptContMod
ON ptContMod.PointControleModeleId = ptCont.PointControleModeleId
INNER JOIN Commande.CommandeTAC cdeTAC
ON cdeTAC.ProjetId = proj.ProjetId
INNER JOIN Commande.CommandeTACCatalogue cdeTACCat
ON cdeTACCat.CommandeTACId = cdeTAC.CommandeTACId
INNER JOIN Fournisseur.Fournisseur four
ON four.FournisseurId = cdeTACCat.FournisseurId
INNER JOIN Fournisseur.ModeTransmission modTrans
ON modTrans.ModeTransmissionId = four.ModeTransmissionId
WHERE ptContMod.PointControleModeleCode = 'Foooooo'
AND ptCont.Etat = 'Fooo'
AND proj.DateLivraison IS NOT NULL
AND DATEADD(DAY, -14, proj.DateLivraison) <= GETDATE()
GROUP BY proj.ProjetId
)
SELECT proj.ProjetId AS ProjetId
FROM Projet.Projet proj
INNER JOIN Workflow.PointControle ptCont
ON ptCont.ProjetId = proj.ProjetId
INNER JOIN Workflow.PointControleModele ptContMod
ON ptContMod.PointControleModeleId = ptCont.PointControleModeleId
INNER JOIN Commande.CommandeTAC cdeTAC
ON cdeTAC.ProjetId = proj.ProjetId
INNER JOIN Commande.CommandeTACCatalogue cdeTACCat
ON cdeTACCat.CommandeTACId = cdeTAC.CommandeTACId
INNER JOIN Fournisseur.Fournisseur four
ON four.FournisseurId = cdeTACCat.FournisseurId
INNER JOIN Fournisseur.ModeTransmission modTrans
ON modTrans.ModeTransmissionId = four.ModeTransmissionId
INNER JOIN Trans ON Trans.projetId = proj.ProjetId
WHERE ptContMod.PointControleModeleCode = 'Foo'
AND ptCont.Etat = 'Fooo'
AND proj.DateLivraison IS NOT NULL
AND DATEADD(DAY, -14, proj.DateLivraison) <= GETDATE()
GROUP BY proj.ProjetId
HAVING COUNT(trans.NbNonSALM) > 0 AND COUNT(trans.NbSALM) = 0
UNION
SELECT projet.ProjetId AS ProjetId
FROM Projet.Projet projet
INNER JOIN Workflow.PointControle ptControle
ON ptControle.ProjetId = projet.ProjetId
INNER JOIN Workflow.PointControleModele ptContMod
ON ptContMod.PointControleModeleId = ptControle.PointControleModeleId
INNER JOIN Commande.CommandeTAC cdeTAC
ON cdeTAC.ProjetId = projet.ProjetId
INNER JOIN Commande.CommandeTACCatalogue cdeTACCat
ON cdeTACCat.CommandeTACId = cdeTAC.CommandeTACId
INNER JOIN commande.AREntete arEnt
ON arEnt.ProjetIdTAC = cdeTAC.ProjetIdTAC
INNER JOIN Commande.Article art
ON art.AREnteteId = arEnt.AREnteteId AND art.CommandeTACCatalogueId = cdeTACCat.CommandeTACCatalogueId
INNER JOIN Fournisseur.Fournisseur four
ON four.FournisseurId = cdeTACCat.FournisseurId
INNER JOIN Fournisseur.ModeTransmission modTrans
ON modTrans.ModeTransmissionId = four.ModeTransmissionId
WHERE ptContMod.PointControleModeleCode = 'Fooo'
AND ptControle.Etat = 'Foo'
AND arEnt.SuppressionLogique = 0
AND arEnt.Statut IS NOT NULL
AND arEnt.Statut >= 4
AND arEnt.Statut != 9
AND modTrans.Code = 'Fooooooo'
AND projet.SiteId = #siteId
END
;
I am not try this, but I think it work for you.. Or you can give some sample data if error comes.
;WITH CTE AS
(
SELECT proj.ProjetId AS ProjetId,
SUM (CASE WHEN modTrans.Code != 'FoO' THEN 1 ELSE 0 END) AS VAL1,
SUM(CASE WHEN modTrans.Code = 'Foo' THEN 1 ELSE 0 END) AS VAL2
FROM Projet.Projet proj
INNER JOIN Workflow.PointControle ptCont
ON ptCont.ProjetId = proj.ProjetId
INNER JOIN Workflow.PointControleModele ptContMod
ON ptContMod.PointControleModeleId = ptCont.PointControleModeleId
INNER JOIN Commande.CommandeTAC cdeTAC
ON cdeTAC.ProjetId = proj.ProjetId
INNER JOIN Commande.CommandeTACCatalogue cdeTACCat
ON cdeTACCat.CommandeTACId = cdeTAC.CommandeTACId
INNER JOIN Fournisseur.Fournisseur four
ON four.FournisseurId = cdeTACCat.FournisseurId
INNER JOIN Fournisseur.ModeTransmission modTrans
ON modTrans.ModeTransmissionId = four.ModeTransmissionId
WHERE ptContMod.PointControleModeleCode = 'FFooooooooo'
AND ptCont.Etat = 'Foooooo'
AND proj.DateLivraison IS NOT NULL
AND [proj].[DateLivraison] <= DATEADD(DAY, 14, GETDATE())
GROUP BY proj.ProjetId
)
SELECT ProjetId, VAL1, VAL2
FROM CTE
GROUP BY ProjetId, VAL1, VAL2
HAVING COUNT(VAL1) > 0 AND COUNT(VAL2) = 0
You cannot use the alias in the HAVING clause. Replace with this instead:
HAVING
SUM(CASE WHEN modTrans.Code != 'FoO' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN modTrans.Code = 'Foo' THEN 1 ELSE 0 END) = 0
Replace your HAVING clause with this
HAVING
SUM (CASE WHEN modTrans.Code != 'FoO' THEN 1 ELSE 0 END)>0
AND
SUM(CASE WHEN modTrans.Code = 'Foo' THEN 1 ELSE 0 END)=0

How to change this 'Not In' Query to Left Join query

I've been trying to change this query. I don't want to use 'Not In' in this query. Can anybody help me how to change this query to left join query?
SELECT t.date,t.ticket,t.weight,t.Count, td.description
FROM tblticket t inner join tblticketdetails td on t.ticket = td.ticket
WHERE t.ticket NOT IN (SELECT r.Original_ticket from tblRenew R where isnull(r.new_ticket,'') = '' and r.transaction_status = 'valid')
AND RTRIM(LTRIM(t.status)) = 'OPEN'
AND td.Type = 62
AND t.weight/t.Count >= 1000
AND t.date BETWEEN '2011-12-31' AND '2013-01-17'
Providing that you don't have multiple records in tblRenew for any ticket:
select
t.date, t.ticket, t.weight, t.Count, td.description
from
tblticket t
inner join tblticketdetails td on t.ticket = td.ticket
left join tblRenew R on isnull(r.new_ticket,'') = '' and r.transaction_status = 'valid' and r.Original_ticket = t.ticket
where
r.Original_ticket is not null
and RTRIM(LTRIM(t.status)) = 'OPEN'
and td.Type = 62
and t.weight/t.Count >= 1000
and t.date BETWEEN '2011-12-31' AND '2013-01-17'
SELECT t.date, t.ticket,t.weight, t.Count, td.description
FROM tblticket t inner join
tblticketdetails td
on t.ticket = td.ticket left outer join
(SELECT r.Original_ticket
from tblRenew R
where isnull(r.new_ticket,'') = '' and
r.transaction_status = 'valid'
) v
on t.ticket = v.Original_ticket
WHERE t.ticket NOT IN (SELECT r.Original_ticket from tblRenew R where isnull(r.new_ticket,'') = '' and r.transaction_status = 'valid')
AND RTRIM(LTRIM(t.status)) = 'OPEN'
AND td.Type = 62
AND t.weight/t.Count >= 1000
AND t.date BETWEEN '2011-12-31' AND '2013-01-17'
and v.original_tiket is null