Self Join Issue - Defining Extracted Time Periods - sql

In the below query, I extract the month in the Select query. I then execute multiple Self Joins using the extracted month. I am getting an
Invalid column name 'mnth'
for every time that field is referenced in the Self Joins. Where would I define the extracted month in the query below?
SELECT MONTH(frcst.InvDate) AS mnth
, frcst.LineCode
, frcst.ClassCode
, cc_type
, rank
, keycust1
, keycust2
, keycust3
, sales1
, sales2
, sales3
, SUM(ship2017.GrossSales) AS gross_sales2017
, SUM(ship2017.QtyShip + ( (ship2017.QtyOrd - ship2017.QtyShip) * 0.25) ) AS frcst_qty2017
, SUM(ship2018.GrossSales) AS gross_sales2018
, SUM(ship2018.QtyShip + ( (ship2018.QtyOrd - ship2018.QtyShip) * 0.25) ) AS frcst_qty2018
, SUM(ship2019.GrossSales) AS gross_sales2019
, SUM(ship2019.QtyShip + ( (ship2019.QtyOrd - ship2019.QtyShip) * 0.25) ) AS frcst_qty2019
, SUM(ship2020.GrossSales) AS gross_sales2020
, SUM(ship2020.QtyShip + ( (ship2020.QtyOrd - ship2017.QtyShip) * 0.25) ) AS frcst_qty2020
FROM FrcstFactTbl frcst
JOIN account_hierarchy_lu account
ON frcst.AccountNumber = account.account_number
JOIN cc_type_lu cct
ON frcst.ClassCode = cct.class_code
JOIN pop_code_lu pop
ON frcst.PartNumber = pop.PartNumber
JOIN FrcstFactTbl ship2017
ON frcst.mnth = ship2017.mnth
AND frcst.LineCode = ship2017.LineCode
AND frcst.ClassCode = ship2017.ClassCode
AND frcst.AccountNumber = ship2017.AccountNumber
JOIN FrcstFactTbl ship2018
ON frcst.mnth = ship2018.mnth
AND frcst.LineCode = ship2018.LineCode
AND frcst.ClassCode = ship2018.ClassCode
AND frcst.AccountNumber = ship2018.AccountNumber
JOIN FrcstFactTbl ship2019
ON frcst.mnth = ship2019.mnth
AND frcst.LineCode = ship2019.LineCode
AND frcst.ClassCode = ship2019.ClassCode
AND frcst.AccountNumber = ship2019.AccountNumber
JOIN FrcstFactTbl ship2020
ON frcst.mnth = ship2020.mnth
AND frcst.LineCode = ship2020.LineCode
AND frcst.ClassCode = ship2020.ClassCode
AND frcst.AccountNumber = ship2019.AccountNumber
WHERE YEAR(ship2017.InvDate) = '2017'
AND YEAR(ship2018.InvDate) = '2018'
AND YEAR(ship2019.InvDate) = '2019'
AND YEAR(ship2020.InvDate) = '2020'
GROUP BY mnth, frcst.LineCode, frcst.ClassCode, cc_type, rank, keycust1, keycust2, keycust3, sales1, sales2, sales3
ORDER BY mnth

The only place you can use a column alias (which is what mnth is) is in the order by clause. Everywhere else you have to use the computation MONTH(frcst.InvDate) or else compute it in a sub-query.
I would use a sub-query i.e. replace this line:
FROM FrcstFactTbl frcst
With this:
FROM (
select *, MONTH(frcst.InvDate) AS mnth
from FrcstFactTbl
) frcst
And of course replace the first line:
SELECT MONTH(frcst.InvDate) AS mnth
With
SELECT mnth

Thank you all. Below is the query that finally worked.
SELECT
masterlist.Month AS [Month]
,masterlist.LineCode AS [Line Code]
,masterlist.ClassCode AS [Class Code]
,ct.cc_type AS [Class Code Type]
,pop.pop_code AS [Pop Code]
,ah.keycust1 AS [Key Cust1]
,ah.keycust2 AS [KeyCust2 - Territory]
,ah.keycust3 AS [Key cust3]
,ah.sales1 AS [Sales1]
,ah.sales2 AS [Sales2]
,ah.sales3 AS [Sales3]
,SUM(ff2017.[Gross]) AS [2017 Gross]
,SUM (ff2017.QtyShip + ( (ff2017.QtyOrd - ff2017.QtyShip) * 0.25) ) AS [2017 Forecast Qty]
,SUM(ff2018.[Gross]) AS [2018 Gross]
,SUM (ff2018.QtyShip + ( (ff2018.QtyOrd - ff2018.QtyShip) * 0.25) ) AS [2018 Forecast Qty]
,SUM(ff2019.[Gross]) AS [2019 Gross]
,SUM (ff2019.QtyShip + ( (ff2019.QtyOrd - ff2019.QtyShip) * 0.25) ) AS [2019 Forecast Qty]
,SUM(ff2020.[Gross]) AS [2020 Gross]
,SUM (ff2020.QtyShip + ( (ff2020.QtyOrd - ff2020.QtyShip) * 0.25) ) AS [2020 Forecast Qty]
FROM (
SELECT
DISTINCT ff.AccountNumber, MONTH(InvDate) AS Month,LineCode,ClassCode,ff.PartNumber
FROM FrcstFactTbl ff
) AS masterlist
LEFT OUTER JOIN
(
SELECT
AccountNumber
,PartNumber
,Month(InvDate) AS Month
,SUM(GrossSales) AS [Gross]
,SUM (QtyShip) AS [QtyShip]
,SUM(QtyOrd) AS [QtyOrd]
FROM FrcstFactTbl WHERE Year(InvDate)=2017
GROUP BY AccountNumber, PartNumber, Month(InvDate)
) AS ff2017 ON masterlist.Month = ff2017.Month AND masterlist.AccountNumber = ff2017.AccountNumber AND masterlist.PartNumber = ff2017.PartNumber
LEFT OUTER JOIN
(
SELECT
AccountNumber
,PartNumber
,Month(InvDate) AS Month
,SUM(GrossSales) AS [Gross]
,SUM (QtyShip) AS [QtyShip]
,SUM(QtyOrd) AS [QtyOrd]
FROM FrcstFactTbl WHERE Year(InvDate)=2018
GROUP BY AccountNumber, PartNumber, Month(InvDate)
) AS ff2018 ON masterlist.Month = ff2018.Month AND masterlist.AccountNumber = ff2018.AccountNumber AND masterlist.PartNumber = ff2018.PartNumber
LEFT OUTER JOIN
(
SELECT
AccountNumber
,PartNumber
,Month(InvDate) AS Month
,SUM(GrossSales) AS [Gross]
,SUM (QtyShip) AS [QtyShip]
,SUM(QtyOrd) AS [QtyOrd]
FROM FrcstFactTbl WHERE Year(InvDate)=2019
GROUP BY AccountNumber, PartNumber, Month(InvDate)
) AS ff2019 ON masterlist.Month = ff2019.Month AND masterlist.AccountNumber = ff2019.AccountNumber AND masterlist.PartNumber = ff2019.PartNumber
LEFT OUTER JOIN
(
SELECT
AccountNumber
,PartNumber
,Month(InvDate) AS Month
,SUM(GrossSales) AS [Gross]
,SUM (QtyShip) AS [QtyShip]
,SUM(QtyOrd) AS [QtyOrd]
FROM FrcstFactTbl WHERE Year(InvDate)=2020
GROUP BY AccountNumber, PartNumber, Month(InvDate)
) AS ff2020 ON masterlist.Month = ff2020.Month AND masterlist.AccountNumber = ff2020.AccountNumber AND masterlist.PartNumber = ff2020.PartNumber
LEFT OUTER JOIN cc_type_lu ct ON masterlist.ClassCode = ct.class_code
LEFT OUTER JOIN pop_code_lu pop ON masterlist.PartNumber = pop.PartNumber
LEFT OUTER JOIN account_hierarchy_lu ah ON masterlist.AccountNumber = ah.account_number
--ORDER BY masterlist.Month
GROUP BY masterlist.Month
,masterlist.LineCode
,masterlist.ClassCode
,ct.cc_type
,pop.pop_code
,ah.keycust1
,ah.keycust2
,ah.keycust3
,ah.sales1
,ah.sales2
,ah.sales3

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 can I optimize a query like this that is taking 17s

A tip would be welcome. I tried to create an expression index on id_contrato but it gave me only 1s of speed. The query is taking 17s. I just need some medium to small improvement . I am using Firebird 2.0.
select sum(VL_EMPENHO) as VL_EMPENHO from (select distinct
E.ID_EMPENHO || '/' || E.ID_EXERCICIO as NUM_EMPENHO,
E.DATA,
E.VALOR + coalesce((select SUM(E__.VALOR) from CONTABIL_EMPENHO E__ where E__.ID_EMPENHO = E.ID_EMPENHO and E__.NUMERO = E.NUMERO
and E__.ID_ORGAO = E.ID_ORGAO and E__.ID_EXERCICIO = E.ID_EXERCICIO
and (E.TIPO_DESPESA = 'EMO' and E__.TIPO_DESPESA = 'EOA')), 0) +
coalesce(( select sum(V.VALOR)
from CONTABIL_VARIACAO V
LEFT JOIN CONTABIL_EVENTO ev on ev.ID_FICHA = v.ID_FICHA and ev.ID_EXERCICIO = v.ID_EXERCICIO
LEFT JOIN CONTABIL_EVENTO_ITEM EI on EI.ID_EVENTO = ev.ID_EVENTO and EI.TIPO_EVENTO = ev.TIPO_EVENTO
LEFT JOIN CONTABIL_PLANO_CONTA PD ON PD.ID_REGPLANO = EI.ID_DEBITO
LEFT JOIN CONTABIL_PLANO_CONTA PC ON PC.ID_REGPLANO = EI.ID_CREDITO
where ((PD.id_plano in ( '632910100', '631990000') or PC.id_plano in ( '632910100', '631990000') ) or (PD.id_plano in ( '195920000', '195910000') or PC.id_plano in ( '195920000', '195910000') ))
AND V.ID_EMPENHO = E.ID_EMPENHO
and V.ANO = E.ID_EXERCICIO and V.ID_ORGAO = E.ID_ORGAO
), 0) as VL_EMPENHO,
(select first 1 P.DATA from CONTABIL_PAGAMENTO P
inner join CONTABIL_EMPENHO E__ on E__.ID_REGEMPENHO = P.ID_REGEMPENHO
where
(E.TIPO_DESPESA = 'EMO' and E__.TIPO_DESPESA in ('EMO', 'SEO', 'EMR', 'SER'))
and E__.ID_EXERCICIO = E.ID_EXERCICIO and E__.ID_ORGAO = E.ID_ORGAO and
E__.ID_EMPENHO = E.ID_EMPENHO and P.ANULACAO = 'N' order by P.ID_PAGTO desc) as DT_PAGTO,
(select sum(P.VALOR) from CONTABIL_PAGAMENTO P
inner join CONTABIL_EMPENHO E__ on E__.ID_REGEMPENHO = P.ID_REGEMPENHO
where
(E.TIPO_DESPESA = 'EMO' and E__.TIPO_DESPESA in ('EMO', 'SEO', 'EMR', 'SER'))
and E__.ID_EXERCICIO = E.ID_EXERCICIO and E__.ID_ORGAO = E.ID_ORGAO and
E__.ID_EMPENHO = E.ID_EMPENHO) as VL_PAGO
from CONTABIL_CONTRATO C
left join CONTABIL_EMPENHO E on substring(E.ID_CONTRATO from 1 for 8) = substring(C.ID_CONTRATO from 1 for 8) and
E.ID_ORGAO = C.ID_ORGAO and E.TIPO_DESPESA in ('EMO')
where C.ID_ORGAO = '020000' and C.ID_CONTRATO like '00072017%' and E.ID_COMPRA <> 0 order by 1, 2)
Many items that may help your query. For indexes, I would start by having the following to help optimize
table index
CONTABIL_EMPENHO ( ID_ORGAO, TIPO_DESPESA, ID_CONTRATO, ID_EMPENHO, ID_EXERCICIO )
CONTABIL_VARIACAO ( ID_ORGAO, ID_EMPENHO, ANO )
CONTABIL_PAGAMENTO ( ID_REGEMPENHO )
Your final WHERE clause includes the 'E' alias which turns your LEFT JOIN to an INNER JOIN, so I just moved the 'AND' clause to the 'E' join section. Since your outer query is doing a SUM() of the inner table results, you do not need the 'order by 1, 2' clause, so I removed that.
You join between
CONTABIL_CONTRATO C join CONTABIL_EMPENHO E
on substring( E.ID_CONTRATO from 1 for 8)
= substring( C.ID_CONTRATO from 1 for 8)
will most probably give you duplicate / false answers because you are comparing on the left 8 characters of the contractor id. So, lets take a look at the following sample data. Notice each of the IDs starts with "12345678" representing the substring from 1 for 8 of equality. This leaves the remainder of the ID that will cause false join results as you will see.
CONTABIL_CONTRATO C
ID_CONTRATO
12345678A
12345678B
12345678C
12345678D
CONTABIL_EMPENHO E
ID_CONTRATO
12345678E
12345678F
12345678G
12345678H
Without seeing actual data, this will create 16 times results via
C.ID =12345678(A) joins to E.12345678(E), E.12345678(F), E.12345678(G) and E.12345678(H)
C.ID =12345678(B) joins to E.12345678(E), E.12345678(F), E.12345678(G) and E.12345678(H)
C.ID =12345678(C) joins to E.12345678(E), E.12345678(F), E.12345678(G) and E.12345678(H)
C.ID =12345678(D) joins to E.12345678(E), E.12345678(F), E.12345678(G) and E.12345678(H)
but then you'll have the same with
(B) joined to (E) (F) (G) (H)
(C) joined to (E) (F) (G) (H)
(D) joined to (E) (F) (G) (H)
and then the inverse
(E) joined to (A) (B) (C) (D)
(F) joined to (A) (B) (C) (D)
(G) joined to (A) (B) (C) (D)
(H) joined to (A) (B) (C) (D)
So, for each instance you keep re-querying the same columns sub-selects over and over to get the same repeats of data which I think is COMPLETELY in-accurate to what you want. But not seeing actual data, can not confirm.
What you PROBABLY want is where the C.contractor ID = E.contractor ID. Your FINAL where clause that is explicitly limiting the scope to contractor like '00072017%' would limit down your results to just those contractors in question. So, I changed the JOIN to be on same matching contractor ID.
But that gets completely eliminated because you are never really using your CONTABIL_CONTRATO table except to do the join to the CONTABIL_EMPENHO. Since the two common columns are in both tables, I just changed the where clause to reference the 'E' columns to the ID_ORGAO and ID_CONTRATO values.
With each of your coalesce(), since the main where clause already has E.TIPO_DESPESA = 'EMO', it is not needed in the inner column-select query.
select
sum( PQ.VL_EMPENHO) VL_EMPENHO
from
(
select distinct
E.ID_EMPENHO || '/' || E.ID_EXERCICIO NUM_EMPENHO,
E.DATA,
E.VALOR
+ coalesce( ( select SUM(E__.VALOR)
from CONTABIL_EMPENHO E__
where
E.ID_ORGAO = E__.ID_ORGAO
and E__.TIPO_DESPESA = 'EOA'
AND E.ID_EMPENHO = E__.ID_EMPENHO
and E.NUMERO = E__.NUMERO
and E.ID_EXERCICIO = E__.ID_EXERCICIO )
, 0)
+ coalesce( ( select sum(V.VALOR)
from CONTABIL_VARIACAO V
LEFT JOIN CONTABIL_EVENTO ev
on v.ID_FICHA = ev.ID_FICHA
and v.ID_EXERCICIO = ev.ID_EXERCICIO
LEFT JOIN CONTABIL_EVENTO_ITEM EI
on ev.ID_EVENTO = EI.ID_EVENTO
and ev.TIPO_EVENTO = EI.TIPO_EVENTO
LEFT JOIN CONTABIL_PLANO_CONTA PD
ON EI.ID_DEBITO = PD.ID_REGPLANO
LEFT JOIN CONTABIL_PLANO_CONTA PC
ON EI.ID_CREDITO = PC.ID_REGPLANO
where
E.ID_ORGAO = V.ID_ORGAO
and E.ID_EMPENHO = V.ID_EMPENHO
and E.ID_EXERCICIO = V.ANO
AND (
( PD.id_plano in ( '632910100', '631990000')
or PC.id_plano in ( '632910100', '631990000')
)
or
( PD.id_plano in ( '195920000', '195910000')
or PC.id_plano in ( '195920000', '195910000')
)
)
)
, 0) as VL_EMPENHO,
( select first 1
P.DATA
from
CONTABIL_EMPENHO E__
inner join CONTABIL_PAGAMENTO P
on E__.ID_REGEMPENHO = P.ID_REGEMPENHO
AND P.ANULACAO = 'N'
where
E.ID_ORGAO = E__.ID_ORGAO
and E.ID_EMPENHO = E__.ID_EMPENHO
and E.ID_EXERCICIO = E__.ID_EXERCICIO
and E__.TIPO_DESPESA in ('EMO', 'SEO', 'EMR', 'SER')
order by
P.ID_PAGTO desc ) as DT_PAGTO,
( select
sum(P.VALOR)
from
CONTABIL_EMPENHO E__
inner join CONTABIL_PAGAMENTO P
on E__.ID_REGEMPENHO = P.ID_REGEMPENHO
where
E.ID_ORGAO = E__.ID_ORGAO
and E.ID_EMPENHO = E__.ID_EMPENHO
and E.ID_EXERCICIO = E__.ID_EXERCICIO
and E__.TIPO_DESPESA in ('EMO', 'SEO', 'EMR', 'SER') ) as VL_PAGO
from
CONTABIL_EMPENHO E
where
E.ID_ORGAO = '020000'
and E.ID_CONTRATO like '00072017%'
and E.TIPO_DESPESA in 'EMO'
and E.ID_COMPRA <> 0 ) PQ
I believe I am accurate in my assessment of your query needs. That and the indexes will perform significantly better.
In outer query you are only using column VL_EMPENHO. So I have removed all the other columns from inner query. It should be executed faster now.
select sum(VL_EMPENHO) as VL_EMPENHO from (select distinct
E.VALOR + coalesce((select SUM(E__.VALOR) from CONTABIL_EMPENHO E__ where E__.ID_EMPENHO = E.ID_EMPENHO and E__.NUMERO = E.NUMERO
and E__.ID_ORGAO = E.ID_ORGAO and E__.ID_EXERCICIO = E.ID_EXERCICIO
and (E.TIPO_DESPESA = 'EMO' and E__.TIPO_DESPESA = 'EOA')), 0) +
coalesce(( select sum(V.VALOR)
from CONTABIL_VARIACAO V
LEFT JOIN CONTABIL_EVENTO ev on ev.ID_FICHA = v.ID_FICHA and ev.ID_EXERCICIO = v.ID_EXERCICIO
LEFT JOIN CONTABIL_EVENTO_ITEM EI on EI.ID_EVENTO = ev.ID_EVENTO and EI.TIPO_EVENTO = ev.TIPO_EVENTO
LEFT JOIN CONTABIL_PLANO_CONTA PD ON PD.ID_REGPLANO = EI.ID_DEBITO
LEFT JOIN CONTABIL_PLANO_CONTA PC ON PC.ID_REGPLANO = EI.ID_CREDITO
where ((PD.id_plano in ( '632910100', '631990000') or PC.id_plano in ( '632910100', '631990000') ) or (PD.id_plano in ( '195920000', '195910000') or PC.id_plano in ( '195920000', '195910000') ))
AND V.ID_EMPENHO = E.ID_EMPENHO
and V.ANO = E.ID_EXERCICIO and V.ID_ORGAO = E.ID_ORGAO
), 0) as VL_EMPENHO
from CONTABIL_CONTRATO C
left join CONTABIL_EMPENHO E on substring(E.ID_CONTRATO from 1 for 8) = substring(C.ID_CONTRATO from 1 for 8) and
E.ID_ORGAO = C.ID_ORGAO and E.TIPO_DESPESA in ('EMO')
where C.ID_ORGAO = '020000' and C.ID_CONTRATO like '00072017%' and E.ID_COMPRA <> 0 order by 1, 2)

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

SQL - Pivot Column data to raw. Not as table header value

Here is my current output format:
This is the output I need:
And here is my code
SELECT
tblPO.PONO,
CONVERT(CHAR(10), tblPO.POEnterdDate, 126) AS PODate,
tblSupplier.SupplierCode + '-' + tblSupplier.SupName AS SupplierName,
tblPOMaterials.MaterialCode + '-' + tblMaterial.MaterialDescription AS [Item Description],
tblPR.PRType AS [SPR or PR],
tblPOFromPR.PRNO AS [PR/SPR],
tblUnit.UnitCode,
tblPOMaterials.POQty AS Qty,
tblPOMaterials.UnitPrice,
tblPOMaterials.POQty * tblPOMaterials.UnitPrice AS [Total Price]
FROM
tblPO
INNER JOIN
tblPOMaterials ON tblPO.PONO = tblPOMaterials.PONO
INNER JOIN
tblMaterial ON tblPOMaterials.MaterialCode = tblMaterial.MaterialCode
INNER JOIN
tblSupplier ON tblPO.POSupplierID = tblSupplier.SupplierID
INNER JOIN
tblPOFromPR ON tblPO.PONO = tblPOFromPR.PONO
AND tblPOMaterials.MaterialCode = tblPOFromPR.MaterialCode
INNER JOIN
tblUnit ON tblMaterial.UnitID = tblUnit.UnitID
INNER JOIN
tblPR ON tblPOFromPR.PRNO = tblPR.PRNO
WHERE
(CONVERT(date, tblPO.PODate) BETWEEN #StartDate AND #EndDate)
AND (tblPO.POType <> 'Service')
AND (tblPO.POType = #Category)
ORDER BY
tblPO.PONO
Try Using Stuff and Distinct
SELECT DISTINCT tblPO.PONO, CONVERT(CHAR(10), tblPO.POEnterdDate, 126) AS PODate, tblSupplier.SupplierCode + '-' + tblSupplier.SupName AS SupplierName,
tblPOMaterials.MaterialCode + '-' + tblMaterial.MaterialDescription AS [Item Description], tblPR.PRType AS [SPR or PR],
STUFF((
SELECT '/' + CAST(T.PRNO AS VARCHAR(100))
FROM dbo.tblPOFromPR T
WHERE tblPO.PONO = T.PONO AND tblPOMaterials.MaterialCode = T.MaterialCode
FOR XML PATH('')),1,1,'') AS [PR/SPR],
tblUnit.UnitCode, tblPOMaterials.POQty AS Qty, tblPOMaterials.UnitPrice,
tblPOMaterials.POQty * tblPOMaterials.UnitPrice AS [Total Price]
FROM tblPO INNER JOIN tblPOMaterials ON tblPO.PONO = tblPOMaterials.PONO
INNER JOIN tblMaterial ON tblPOMaterials.MaterialCode = tblMaterial.MaterialCode
INNER JOIN tblSupplier ON tblPO.POSupplierID = tblSupplier.SupplierID
INNER JOIN tblPOFromPR ON tblPO.PONO = tblPOFromPR.PONO AND tblPOMaterials.MaterialCode = tblPOFromPR.MaterialCode
INNER JOIN tblUnit ON tblMaterial.UnitID = tblUnit.UnitID
INNER JOIN tblPR ON tblPOFromPR.PRNO = tblPR.PRNO
WHERE (CONVERT(date, tblPO.PODate) BETWEEN #StartDate AND #EndDate) AND (tblPO.POType <> 'Service') AND (tblPO.POType = #Category)
ORDER BY tblPO.PONO

SQL Server 2008 Specified column was specified multiple times

The below code throws the following exception. How can I fix this?
Msg 8156, Level 16, State 1, Line 17
The column 'id' was specified multiple times for 'QISproduct'.
Query:
SELECT
g.artcode
, sum(g.aantal)
, i.class_01
, i.Isstockitem
FROM
gbkmut AS g
INNER JOIN
items AS i ON i.itemcode = g.artcode
INNER JOIN
(SELECT
QISP.id
, QISprocess.nml
, QISeventlog.id
, QISeventlog.dtsample
, QISproduct.nms
, QISbatchlog.nm
, QIStestlog.idvariable
, QIStestlog.no
, QISshortnote.ds
, gewicht = CASE QIStestlog.IDvariable
WHEN '139'
THEN QIStestlog.no
END
, aantal = CASE QIStestlog.IDvariable
WHEN '234'
THEN QIStestlog.no
END
, siloleeg = CASE QIStestlog.idvariable
WHEN '23'
THEN CASE QIStestlog.no
WHEN '10'
THEN 'Ja'
ELSE 'Nee'
END
END
, QISvariable.nml
, gl.nm
, QISprocess.id
FROM
QIC.Vobra_new2.dbo.production AS QISP
INNER JOIN
QIC.Vobra_new2.dbo.process AS QISprocess ON QISP.idprocess = QISProcess.id
INNER JOIN
QIC.Vobra_new2.dbo.product AS QISproduct ON QISP.idproduct = QISproduct.id
INNER JOIN
QIC.Vobra_new2.dbo.batchlog AS QISbatchlog ON QISP.idbatch = QISbatchlog.id
INNER JOIN
QIC.Vobra_new2.dbo.eventlog AS QISeventlog ON QISeventlog.idproduction = QISP.id
AND QISeventlog.idbatch = QISbatchlog.id
INNER JOIN
QIC.Vobra_new2.dbo.testlog AS QIStestlog ON QIStestlog.idevent = QISeventlog.id
LEFT OUTER JOIN
QIC.Vobra_new2.dbo.shortnote AS QISshortnote ON QISshortnote.id = QIStestlog.no
AND QIStestlog.idvariable = '144'
INNER JOIN
QIC.Vobra_new2.dbo.variable AS QISvariable ON QISvariable.id = QIStestlog.idvariable
LEFT OUTER JOIN
QIC.Vobra_new2.dbo.vvarxproc AS vvp ON vvp.idvariable = QISvariable.id
AND vvp.idprocess = QISP.idprocess
LEFT OUTER JOIN
QIC.Vobra_new2.dbo.attribute AS QISattribute ON QISattribute.id = vvp.idattribute
LEFT OUTER JOIN
QIC.Vobra_new2.dbo.grade AS QISgrade ON QISgrade.id = QISattribute.idgrade
LEFT OUTER JOIN
QIC.Vobra_new2.dbo.gradelevel AS gl ON gl.idgrade = QISattribute.idgrade
AND gl.nlevel = QIStestlog.no
WHERE
QISbatchlog.nm NOT LIKE 'V%'
AND QISP.dtstart > '2017-01-01'
AND QISP.dtstart < '2017-01-19'
AND QISP.idprocess IN ('12', '13', '14', '15', '16', '17', '18', '41')
AND QIStestlog.idvariable IN ('234', '139', '128')
) QISproduct ON g.artcode = QISproduct.nms
WHERE
g.bkjrcode > '2015'
AND g.reknr IN (3000, 3010, 3020)
AND g.aantal > 0
AND g.warehouse IN ('1', '9')
AND g.datum >= '2017-01-01'
AND g.oorsprong = 'R'
AND g.kstplcode <> 'VPR'
GROUP BY
g.artcode, i.Class_01, i.IsStockItem
The computed query aliased to QISProduct contains id column from two tables i.e. QISEventLog and QISProcess. So rename those columns to different names. Updated query
SELECT g.artcode
,sum(g.aantal)
,i.class_01
,i.Isstockitem
FROM gbkmut AS g
INNER JOIN items AS i ON i.itemcode = g.artcode
INNER JOIN (
SELECT QISP.id
,QISprocess.nml AS Processnml
,QISeventlog.id AS EventLogId
,QISeventlog.dtsample
,QISproduct.nms
,QISbatchlog.nm AS batchnm
,QIStestlog.idvariable
,QIStestlog.no
,QISshortnote.ds
,gewicht = CASE QIStestlog.IDvariable
WHEN '139'
THEN QIStestlog.no
END
,aantal = CASE QIStestlog.IDvariable
WHEN '234'
THEN QIStestlog.no
END
,siloleeg = CASE QIStestlog.idvariable
WHEN '23'
THEN CASE QIStestlog.no
WHEN '10'
THEN 'Ja'
ELSE 'Nee'
END
END
,QISvariable.nml variablenml
,gl.nm AS glnm
,QISprocess.id AS ProcessId
FROM QIC.Vobra_new2.dbo.production AS QISP
INNER JOIN QIC.Vobra_new2.dbo.process AS QISprocess ON QISP.idprocess = QISProcess.id
INNER JOIN QIC.Vobra_new2.dbo.product AS QISproduct ON QISP.idproduct = QISproduct.id
INNER JOIN QIC.Vobra_new2.dbo.batchlog AS QISbatchlog ON QISP.idbatch = QISbatchlog.id
INNER JOIN QIC.Vobra_new2.dbo.eventlog AS QISeventlog ON QISeventlog.idproduction = QISP.id
AND QISeventlog.idbatch = QISbatchlog.id
INNER JOIN QIC.Vobra_new2.dbo.testlog AS QIStestlog ON QIStestlog.idevent = QISeventlog.id
LEFT JOIN QIC.Vobra_new2.dbo.shortnote AS QISshortnote ON QISshortnote.id = QIStestlog.no
AND QIStestlog.idvariable = '144'
INNER JOIN QIC.Vobra_new2.dbo.variable AS QISvariable ON QISvariable.id = QIStestlog.idvariable
LEFT JOIN QIC.Vobra_new2.dbo.vvarxproc AS vvp ON vvp.idvariable = QISvariable.id
AND vvp.idprocess = QISP.idprocess
LEFT JOIN QIC.Vobra_new2.dbo.attribute AS QISattribute ON QISattribute.id = vvp.idattribute
LEFT JOIN QIC.Vobra_new2.dbo.grade AS QISgrade ON QISgrade.id = QISattribute.idgrade
LEFT JOIN QIC.Vobra_new2.dbo.gradelevel AS gl ON gl.idgrade = QISattribute.idgrade
AND gl.nlevel = QIStestlog.no
WHERE QISbatchlog.nm NOT LIKE 'V%'
AND QISP.dtstart > '2017-01-01'
AND QISP.dtstart < '2017-01-19'
AND QISP.idprocess IN (
'12'
,'13'
,'14'
,'15'
,'16'
,'17'
,'18'
,'41'
)
AND QIStestlog.idvariable IN (
'234'
,'139'
,'128'
)
) QISproduct ON g.artcode = QISproduct.nms
WHERE g.bkjrcode > '2015'
AND g.reknr IN (
3000
,3010
,3020
)
AND g.aantal > 0
AND g.warehouse IN (
'1'
,'9'
)
AND g.datum >= '2017-01-01'
AND g.oorsprong = 'R'
AND g.kstplcode <> 'VPR'
GROUP BY g.artcode
,i.Class_01
,i.IsStockItem
, QISbatchlog.nm
And
, gl.nm
Have same column name
You can add as to change colum name
, gl.nm as col1
You have multiple issues in your query. You are populating following columns with same column name in your inner query. Use Unique name using AS alias in inner query.
QISP.id
QISeventlog.id
QISprocess.id
gl.nm
QISbatchlog.nm
QISprocess.nml
QISvariable.nml
It is mandatory to have unique column name return by select list in sql.