有更好的方法对列求和吗?

问题描述 投票:0回答:1

我有我需要的答案,但我想问是否有更好的方法来获得相同的答案。 “4”将是本月的参数。我正在尝试获取年初至今的预算数字。该表没有日期列,因此这是一种根据周期获取 SUM 的奇怪方法。

SELECT СASE 
         WHEN 4 <= 1 THEN SUM(Period.A)
         WHEN 4 <= 2 THEN SUM(Period.A) + SUM(Period.B)
         WHEN 4 <= 3 THEN SUM(Period.A) + SUM(Period.B) + SUM(Period.C)
         WHEN 4 <= 4 THEN SUM(Period.A) + SUM(Period.B) + SUM(Period.C) + SUM(Period.D)
         WHEN 4 <= 5 THEN SUM(Period.A) + SUM(Period.B) + SUM(Period.C) + SUM(Period.D) 
                        + SUM(Period.E)
         WHEN 4 <= 6 THEN SUM(Period.A) + SUM(Period.B) + SUM(Period.C) + SUM(Period.D) 
                        + SUM(Period.E) + SUM(Period.F)
         WHEN 4 <= 7 THEN SUM(Period.A) + SUM(Period.B) + SUM(Period.C) + SUM(Period.D) 
                        + SUM(Period.E) + SUM(Period.F) + SUM(Period.G)
         WHEN 4 <= 8 THEN SUM(Period.A) + SUM(Period.B) + SUM(Period.C) + SUM(Period.D) 
                        + SUM(Period.E) + SUM(Period.F) + SUM(Period.G) + SUM(Period.H)
      ELSE 0 
      END AS [LaborCOGS-CO],
   '0' AS [LaborCOGS-AO], '0' AS IndirectLabor,
   '0' AS MiscExpense,    '0' AS LabelCost,
   '0' AS BuildMaint,     '0' AS ShipCost,
   '0' AS RDR,            '0' AS NetSales
From GLAccountBudgetDetails
LEFT JOIN GLAccountBudget WITH(NOLOCK) 
    ON GLAccountBudgetDetails.GLAccountBudgetID = GLAccountBudget.GLAccountBudgetID
LEFT JOIN
( SELECT GLAccountBudgetDetailID,[BudgetAmtPeriod1] A,[BudgetAmtPeriod2] B,
     [BudgetAmtPeriod3] C,[BudgetAmtPeriod4] D,[BudgetAmtPeriod5] E,
     [BudgetAmtPeriod6] F,[BudgetAmtPeriod7] G,[BudgetAmtPeriod8] H,
     [BudgetAmtPeriod9] I,[BudgetAmtPeriod10] J,[BudgetAmtPeriod11] K,
     [BudgetAmtPeriod12] L
  From GLAccountBudgetDetails
) AS Period 
   ON GLAccountBudgetDetails.GLAccountBudgetDetailID = [Period].GLAccountBudgetDetailID
WHERE GLAccountBudgetDetails.GLAccountID IN(256,257,258,266) 
   AND GLAccountBudget.FiscalYear = 2024

这是 GLAccountBudgetDetails 表。最后四列都是 NULL,所以没有帮助。

COLUMN_NAME DATA_TYPE
GLAccountBudgetDetailID int
GLAccountBudgetID   int
GLAccountID int
BudgetAmtPeriod1    float
BudgetAmtPeriod2    float
BudgetAmtPeriod3    float
BudgetAmtPeriod4    float
BudgetAmtPeriod5    float
BudgetAmtPeriod6    float
BudgetAmtPeriod7    float
BudgetAmtPeriod8    float
BudgetAmtPeriod9    float
BudgetAmtPeriod10   float
BudgetAmtPeriod11   float
BudgetAmtPeriod12   float
BudgetAmtPeriod13   float
BudgetAmtPeriod14   float
BudgetAmtPeriod15   float
UserCreated varchar
DateCreated datetime
UserModified    varchar
DateModified    datetime

这是 GLAccountBudget 表。

COLUMN_NAME DATA_TYPE
GLAccountBudgetID   int
Name    varchar
FiscalYear  int
DefaultBudget   bit
UserCreated varchar
DateCreated datetime
UserModified    varchar
DateModified    datetime
sql t-sql
1个回答
0
投票

创建一个视图,将数据标准化为每个周期一行。然后查询该视图。至少你只需要做一次。

这是您问题的简化版本。

create table bad_schema (
  some_id integer not null,
  month1 integer,
  month2 integer,
  month3 integer,
  month4 integer,
  month5 integer,
  month6 integer,
  month7 integer,
  month8 integer,
  month9 integer,
  month10 integer,
  month11 integer,
  month12 integer,
  year integer not null,
  primary key(some_id, year)
);

我们可以创建一个视图,将其转换为 some_id、日期和数据。

create view good_schema as (
  select 
    some_id,
    cast(concat(year, '-', months.value, '-', '01') as date) as this_month,
    case months.value
    when 1 then month1
    when 2 then month2
    when 3 then month3
    when 4 then month4
    when 5 then month5
    when 6 then month6
    when 7 then month7
    when 8 then month8
    when 9 then month9
    when 10 then month10
    when 11 then month11
    when 12 then month12
    else 'what'
    end as data
  from bad_schema
  cross join (
    select * from generate_series(1, 12)
  ) as months
)

然后我们就可以查询了。

select sum(data) 
from good_schema
where this_month between '2023-01-01' and '2023-05-01'
group by some_id

示范.

您可以反转此技术并将表更改为合理的并留下视图以支持遗留查询。

© www.soinside.com 2019 - 2024. All rights reserved.