У меня есть ответ, который мне нужен, но я спрашиваю, есть ли лучший способ получить тот же ответ. «4» будет параметром ThisMonth. Я пытаюсь получить цифры бюджета с начала года. В таблице нет столбца даты, отсюда и такой странный способ получения СУММЫ на основе периода.
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
@Luuk Я не владею базой данных, однако предлагаете ли вы мне добавить индекс для каждой группы столбцов вместо того, чтобы называть их отдельно??
Нет, я ничего не предлагаю, пока не увижу структуру таблицы (DDL) для всех задействованных таблиц.
Дабл (сам) Присоединяйтесь GLAccountBudgetDetails.GLAccountBudgetDetailID = [Period].GLAccountBudgetDetailID
кажется совершенно ненужным.
Пожалуйста, взгляните на: Реальные, с плавающей запятой и деньги и Что такое DDL и DML?
Плохие схемы означают плохие запросы. Мы можем создать представление , чтобы представить, что это хорошая схема с одной строкой за период. Затем запросите это представление. По крайней мере, тогда вам нужно будет сделать это только один раз.
Вот упрощенная версия вашей проблемы.
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 * from good_schema
some_id this_month data
1 2023-01-01 1
1 2023-02-01 2
1 2023-03-01 3
1 2023-04-01 4
1 2023-05-01 5
1 2023-06-01 6
1 2023-07-01 7
...etc...
select sum(data)
from good_schema
where this_month between '2023-01-01' and '2023-05-01'
group by some_id
Демонстрация.
Вы можете перевернуть этот метод и изменить таблицу, чтобы она была разумной, и оставить представление для поддержки устаревших запросов.
Ответ: «В таблице нет столбца даты, отсюда и такой странный способ....», или на codereview.stackexchange.com . на dba.stackexchange.com они предложили бы добавить index.