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

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

Related

How can I sum the total based on a column in Firebird 2.5

How can get totalizations out of a group, especifically in Firebird 2.5.
I have the following query, it's big but it's simple, it has only some inner joins that are correlated.
SELECT "patrimônio", porc_residual AS "percentual residual", vida_util AS "vida útil",
vida_util_meses "vida útil meses", valor_base AS "valor aquisição/valor reavaliação",
"data de incorporação", VALOR_DEPRECIADO AS "valor depreciado" ,
grupo_audesp AS "grupo contábil", sum(dt_depreciado) over(ORDER BY grupo_audesp ) td
FROM
(
SELECT m.nome AS "patrimônio", t.PORC_RESIDUAL, t.VIDA_UTIL, t.VIDA_UTIL_MESES,
lpad(EXTRACT(DAY FROM t.dt_cadastro),2, '0') || '/' || lpad(EXTRACT(month FROM t.dt_cadastro),2, '0') || '/' || EXTRACT(year FROM t.dt_cadastro) "data de incorporação"
,t.placa, GA.ID_AUDESP, GA.NOME AS GRUPO_AUDESP,
T.VALOR as valor,
CASE WHEN (SELECT min(D.VALOR_NOVO)
FROM patrimonio_depreciacao D WHERE D.id_tombamento = T.id_tombamento
AND T.ID_ORGAO = '030000' AND T.SITUACAO IN('A','B')
AND D.REFERENCIA2 >=202201 AND D.REFERENCIA2 <=202201 ) IS NULL THEN(
case when (select max(d.valor_anterior)
from patrimonio_depreciacao D where D.id_tombamento = T.id_tombamento and
T.SITUACAO IN('A','B')
AND d.referencia2 >202201 ) IS NULL THEN T.VALOR_ATUAL ELSE
(select max(d.valor_anterior)
from patrimonio_depreciacao D where D.id_tombamento = T.id_tombamento and
T.SITUACAO IN('A','B')
AND d.referencia2 >202201 )
END)
ELSE
(SELECT min(D.VALOR_NOVO)
FROM patrimonio_depreciacao D WHERE D.id_tombamento = T.id_tombamento
AND T.ID_ORGAO = '030000' AND T.SITUACAO IN('A','B')
AND D.REFERENCIA2 >=202201 AND D.REFERENCIA2 <=202201 ) END as valor_atual,
(SELECT sum(D.VALOR_DEPRECIADO)
FROM patrimonio_depreciacao D WHERE D.id_tombamento = T.id_tombamento
AND T.ID_ORGAO = '030000'
AND D.REFERENCIA2 >=202201 AND D.REFERENCIA2 <=202201 ) as valor_depreciado, T.DT_AQUISICAO,
PS.NOME,
case when (select first 1 pri.vl_reavaliacao from patrimonio_reavaliacao_item pri
inner join patrimonio_reavaliacao pr on pr.id_reavaliacao = pri.id_reavaliacao_item
where pri.id_tombamento = t.id_tombamento
and pr.data<='2022-01-31'
and pr.encerrado ='S'
order by pr.data desc) is null then t.vl_base_depreciacao
else
(select first 1 pri.vl_reavaliacao from patrimonio_reavaliacao_item pri
inner join patrimonio_reavaliacao pr on pr.id_reavaliacao = pri.id_reavaliacao_item
where pri.id_tombamento = t.id_tombamento
and pr.data <= '2022-01-31'
and pr.encerrado ='S'
order by pr.data desc) end as valor_base
FROM PATRIMONIO_TOMBAMENTO T
LEFT JOIN PATRIMONIO_GRUPO_AUDESP GA ON GA.ID_GRUPO_AUDESP = T.ID_GRUPO_AUDESP
LEFT JOIN ESTOQUE_MATERIAL M ON M.ID_MATERIAL = T.ID_MATERIAL
LEFT JOIN PATRIMONIO_SETOR PS ON (T.ID_SETOR = PS.ID_SETOR)
WHERE T.ID_ORGAO = '030000'
AND (T.SITUACAO IN('A') or ( T.SITUACAO = 'B' AND T.DT_BAIXA >'2022-01-31'))
AND (T.DT_REATIVADO IS NULL OR T.DT_REATIVADO<= '2022-01-31' or (T.DT_BAIXA >'2022-01-31'))
AND T.dt_cadastro <= '2022-01-31'
AND PS.TIPO_SETOR = 'S'
ORDER BY GA.ID_AUDESP, t.DT_CADASTRO) t
I think most import is the result
I want to sum "valor depreciado" and "valor aquisição/valor reavaliação" based on those groups.
to make it simple it could be an additional column that repeats the sum in all rows for the entire group.

How Optimize Sum SQL Query?

I have this query.
select a.NoSPKJahit as 'TglSPKJahit',
c.TglSPKJahit as 'spkJahit',
a.SeriBarang as 'KodeSeri',
b.NamaBarang as 'NamaBarang',
a.JmlTotalPotong-a.JmlTotalRusakSablon as 'JumlahSPKJahit',
a.JmlTotalSelesaiJahit as 'JumlahHasilJahit',
(select sum(Qty) from PenjualanDTL where KodeBarang = a.KodeBarang) as 'JumlahPenjualan',
(select sum(JumlahRetur) from StokBS where KodeBarang = a.KodeBarang) as 'JumlahRetur',
(select sum(JumlahRusak) from StokBS where KodeBarang = a.KodeBarang) as 'JumlahRusak',
(a.JmlTotalSelesaiJahit - (select sum(Qty) from PenjualanDTL where KodeBarang = a.KodeBarang) +((select sum(JumlahRetur) from StokBS where KodeBarang = a.KodeBarang)-(select sum(JumlahRusak) from StokBS where KodeBarang = a.KodeBarang))) as 'SisaBarang',
(select sum(JumlahStok) from StokToko where KodeBarang = a.KodeBarang and KodeToko = 'GD000')as 'Gudang',
(select sum(JumlahStok) from StokToko where KodeBarang = a.KodeBarang and KodeToko = 'GD001')as 'GudangAtas',
(select sum(JumlahStok) from StokToko where KodeBarang = a.KodeBarang and KodeToko = 'GD002')as 'Mobil',
(select sum(JumlahStok) from StokToko where KodeBarang = a.KodeBarang and KodeToko = 'OL01')as 'MissMode',
(select sum(JumlahStok) from StokToko where KodeBarang = a.KodeBarang and KodeToko = 'TK005')as 'SilverLeafM'
from DetilBarang a
left join MsBarang b on b.KodeBarang = a.KodeBarang
left join SPKJahit c on c.NoSPKJahit = a.NoSPKJahit
but have very slow performace. How can i speed up query performance ?
Thanks.
I'd move the subqueries to the join clause and use conditional aggregation (SUM(CASE WHEN ...) for all the StokToko.JumlahStok sums.
select
db.NoSPKJahit as "TglSPKJahit",
sj.TglSPKJahit as "spkJahit",
db.SeriBarang as "KodeSeri",
mb.NamaBarang as "NamaBarang",
db.JmlTotalPotong - db.JmlTotalRusakSablon as "JumlahSPKJahit",
db.JmlTotalSelesaiJahit as "JumlahHasilJahit",
pd."JumlahPenjualan",
sb."JumlahRetur",
sb."JumlahRusak",
db.JmlTotalSelesaiJahit - pd."JumlahPenjualan" + sb."JumlahRetur" - sb."JumlahRusak"
as "SisaBarang",
st."Gudang",
st."GudangAtas",
st."Mobil",
st."MissMode",
st."SilverLeafM"
from DetilBarang db
left join MsBarang mb on mb.KodeBarang = db.KodeBarang
left join SPKJahit sj on sj.NoSPKJahit = db.NoSPKJahit
left join
(
select
KodeBarang,
sum(Qty) as "JumlahPenjualan"
from PenjualanDTL
group by KodeBarang
) pd on pd.KodeBarang = db.KodeBarang
left join
(
select
KodeBarang,
sum(JumlahRetur) as "JumlahRetur",
sum(JumlahRusak) as "JumlahRusak"
from StokBS
group by KodeBarang
) sb on sb.KodeBarang = db.KodeBarang
left join
(
select
KodeBarang,
sum(case when KodeToko = 'GD000' then JumlahStok end) as "Gudang",
sum(case when KodeToko = 'GD001' then JumlahStok end) as "GudangAtas",
sum(case when KodeToko = 'GD002' then JumlahStok end) as "Mobil",
sum(case when KodeToko = 'OL01' then JumlahStok end) as "MissMode",
sum(case when KodeToko = 'TK005' then JumlahStok end) as "SilverLeafM"
from StokToko
group by KodeBarang
) st on st.KodeBarang = db.KodeBarang
order by db.NoSPKJahit;
Please change the left outer joins to inner joins where appropriate.
Recommended indexes to speed up the query:
create index idx1 on msbarang (kodebarang, namabarang);
create index idx2 on spkjahit (nospkjahit, tglspkjahit);
create index idx3 on penjualandtl (kodebarang, qty);
create index idx4 on stokbs (kodebarang, jumlahretur, jumlahrusak);
create index idx5 on stoktoko (kodebarang, kodetoko, jumlahstok);
This may be as fast as it gets. Without any WHERE clause you are probably querying a lot of data.
you can try this
SELECT A.*, sum(ISNULL(B.qty, 0)) as TotQty
from SiteInformation A
left join ItemSite B on A.SiteID = B.SiteID and A.InvtID = B.InvtID
I Think it will work better than TotQty = (SELECT SUM(Qty) FROM where...)

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.

Oracle SQL - connecting 2 dates

I have the following code.
It has 2 dates:
1.
(case
when not trunc(iv.dated) is null then trunc(iv.dated) else trunc(iv1.dated)
end) date_stock_received
2.
trunc(dh.actshpdate) SHIP_DATE
Is there a way to join the dates so they show in one column?
select unique li.catnr, li.av_part_no,
(select sum(pl.qty_onhand) from part_loc pl where li.av_part_no = pl.part_no) qty_onhand,
(case
when not trunc(iv.dated) is null then trunc(iv.dated) else trunc(iv1.dated)
end) date_stock_received,
(case
when not sum(iv.quantity) is null then sum(iv.quantity) else sum(iv1.quantity)
end) qty_received,
dp.delqty, od.ord_extordnr, trunc(dh.actshpdate) SHIP_DATE
from leos_item li
LEFT JOIN scm_packtyp sp
ON li.packtyp = sp.packtyp
LEFT JOIN invtran_view_oes iv
ON li.av_part_no = iv.part_no
and (iv.transaction = 'NREC' and iv.location_no = ' RETURNS W')
LEFT JOIN invtran_view_oes iv1
on li.av_part_no = iv1.part_no
and (iv1.transaction = 'CORR+' and iv1.remark like 'STOCK FROM SP PALLET%')
LEFT JOIN oes_delsegview od
ON od.catnr = li.catnr
and od.prodtyp = li.prodtyp
and od.packtyp = li.packtyp
LEFT JOIN oes_dpos dp
ON od.ordnr = dp.ordnr
and od.posnr = dp.posnr
and od.segnr = dp.segnr
LEFT JOIN oes_dhead dh
on dp.dheadnr = dh.dheadnr
and dh.shpfromloc = 'W'
where li.cunr = '816900'
and substr(li.catnr,1,5) in ('RGMCD','RGJCD')
and li.item_type = 'FP'
and li.catnr = 'RGJCD221'
group by li.catnr, li.av_part_no, iv.dated, iv.quantity, iv1.dated, iv1.quantity, dp.delqty,
dp.ordnr, dp.posnr, dp.segnr, od.ord_extordnr, dh.actshpdate
order by li.av_part_no
Current result is ...
... what I would like to see is ...
Is this possible ?
The coalesce function might be what you want.
select trunc(coalesce(iv.dated, iv1.dated, dh.actshpdate)) theDateYouMightWant

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