Home > Mobile >  SQL Nested Sum(probably ?)
SQL Nested Sum(probably ?)

Time:10-14

I got a select that groups the total value of a column, but also I need the percentage referring to each sum referring to the total sum!

As an example of today's return:

id|sum
 1| 10
 2| 50
 3| 80
 4| 20
 5| 60

What I'm looking for: (the total is 220)

id|sum|     %
 1| 10|10/220
 2| 50|50/220
 3| 80|80/220
 4| 20|20/220
 5| 60|60/220

I am not sure if there's an easy way to got that result, using a sub select I could do this but I tought it not good and should have a better way.

The select is so simple:

Select
   id,
   sum(value)
From
   table
Group By
   id

But, that's the real select:

Select
   OrcaItem.Cd_Produto,
   OrcaItem.Ds_Produto,
   OrcaItem.Cd_Produto || ' - ' || OrcaItem.Ds_Produto CdDs_Produto,
   Estoque.Qt_Disponivel,
   Sum(OrcaItem.Qt_Vendida) Qt_Vendida,
   Sum(OrcaItem.Vr_TotalLiquido) Vr_Liquido, -- HERE!
   Cast(Sum(
      Case :piTipoCusto
         When 0 Then (Produto.Vr_CustoAtual * OrcaItem.Qt_Vendida)
         When 1 Then (OrcaItem.Vr_CustoAtual * OrcaItem.Qt_Vendida)
         When 2 Then (OrcaItem.Vr_CustoFin * OrcaItem.Qt_Vendida)
         When 3 Then (Produto.Vr_UltPcoCompra * OrcaItem.Qt_Vendida)
      End
   ) As Numeric(15,2)) Vr_Custo,
   Cast(Sum(
      Case :piTipoCusto
         When 0 Then OrcaItem.Vr_TotalLiquido - (Produto.Vr_CustoAtual * OrcaItem.Qt_Vendida)
         When 1 Then OrcaItem.Vr_TotalLiquido - (OrcaItem.Vr_CustoAtual * OrcaItem.Qt_Vendida)
         When 2 Then OrcaItem.Vr_TotalLiquido - (OrcaItem.Vr_CustoFin * OrcaItem.Qt_Vendida)
         When 3 Then OrcaItem.Vr_TotalLiquido - (Produto.Vr_UltPcoCompra * OrcaItem.Qt_Vendida)
      End
   ) As Numeric(15,2)) Vr_Lucro,
   Sum(
      Case :piTipoCusto
         When 0 Then OrcaItem.Vr_TotalLiquido - (Produto.Vr_CustoAtual * OrcaItem.Qt_Vendida)
         When 1 Then OrcaItem.Vr_TotalLiquido - (OrcaItem.Vr_CustoAtual * OrcaItem.Qt_Vendida)
         When 2 Then OrcaItem.Vr_TotalLiquido - (OrcaItem.Vr_CustoFin * OrcaItem.Qt_Vendida)
         When 3 Then OrcaItem.Vr_TotalLiquido - (Produto.Vr_UltPcoCompra * OrcaItem.Qt_Vendida)
      End
   ) / Sum(OrcaItem.Vr_TotalLiquido) * 100 Pc_Lucro,
   Produto.Cd_Linha,
   Linha.Ds_Linha,
   Produto.Cd_Grupo,
   Grupo.Ds_Grupo
From
   OrcaItem
Inner Join Orca On Orca.Nr_Orcamento = OrcaItem.Nr_Orcamento
Inner Join Estoque On Estoque.Cd_Produto = OrcaItem.Cd_Produto
Inner Join Produto On Produto.Cd_Produto = OrcaItem.Cd_Produto
Inner Join Linha On Linha.Cd_Linha = Produto.Cd_Linha
Inner Join Grupo On Grupo.Cd_Linha = Produto.Cd_Linha And
                    Grupo.Cd_Grupo = Produto.Cd_Grupo
Where
   Orca.Fg_Situacao In ('F', 'R') And
   Orca.Dt_Atendido Between :piDt_Inicio And :piDt_Final
Group By
   OrcaItem.Cd_Produto,
   OrcaItem.Ds_Produto,
   CdDs_Produto,
   Estoque.Qt_Disponivel,
   Produto.Cd_Linha,
   Linha.Ds_Linha,
   Produto.Cd_Grupo,
   Grupo.Ds_Grupo
Order By
   Produto.Cd_Linha,
   Produto.Cd_Grupo,
   OrcaItem.Ds_Produto

Sum(OrcaItem.Vr_TotalLiquido) Vr_Liquido = total of each

The 'global' total is the sum of Vr_Liquido.

CodePudding user response:

What you are looking for is Window Functions.

CodePudding user response:

Assuming the simple select you show, you can use a window function, assuming you're using Firebird 3.0 or higher:

select id, sum_value, cast(sum_value as numeric(18,2)) / sum(sum_value) over()
from (
  select id, sum("VALUE") as sum_value
  from testdata
  group by id
)

The over() will aggregate over all rows. The cast to NUMERIC(18,2) is needed to ensure the value is non-zero. Use a higher scale if you need more digits (or cast to double precision).

For the more complex select, you take the same approach. Make the original query a derived table (or common table expression), and use the window function in the enclosing select list.

  • Related