SQL получает все столбцы в определенной строке, чья сумма больше заданного значения - PullRequest
0 голосов
/ 24 апреля 2018

Я работаю с существующей таблицей (не могу ее изменить) в SQL 2014

Упрощенная (пример) структура таблицы:

CREATE TABLE dbo.T1
(
    sYear int NOT NULL,
    m1 decimal(18, 2) NOT NULL,
    m2 decimal(18, 2) NOT NULL,
    m3 decimal(18, 2) NOT NULL,
    m4 decimal(18, 2) NOT NULL,
    m5 decimal(18, 2) NOT NULL,
    m6 decimal(18, 2) NOT NULL,
    m7 decimal(18, 2) NOT NULL,
    m8 decimal(18, 2) NOT NULL,
    m9 decimal(18, 2) NOT NULL,
    m10 decimal(18, 2) NOT NULL,
    m11 decimal(18, 2) NOT NULL,
    m12 decimal(18, 2) NOT NULL
)

Таблица представляет собой «месячный бюджет» иличто от этого осталось, где от m1 до m12 представляют месяцы

Итак, пример данных для строки будет выглядеть примерно так:

Insert into dbo.T1 
Values( 2017,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000)

Теперь моя задача такова, если пользователь хочет потратитьсумма в конкретном месяце, мне нужно удалить сумму расходов из этого конкретного месяца, оставшегося бюджета, при условии, что у него достаточно средств.Если нет, мне нужно удалить форму в последующие месяцы, пока не будет удалена полная стоимость расходов.

Я пытался использовать операторы Case и столбцы суммирования, но это стало смехотворно длинным .... слишком много случаев.Итак, в итоге я создал временную таблицу, в которой каждый столбец из исходной таблицы становится строкой, а затем суммировал значения строк до тех пор, пока я не достиг суммы расходов. (Использовал этот ответ в качестве примера того, как этого добиться: Выберите промежуточную сумму, пока не будет достигнута конкретная сумма )

Все еще не уверен, что это лучший способ для моего сценария, поэтому кто-нибудь знает способ суммирования по столбцам определенной строки илилюбой другой / лучший способ достижения этого?

1 Ответ

0 голосов
/ 25 апреля 2018

Хорошо, так что это мое решение ... Это работает, как я сказал в вопросе, но я не уверен, что это самый эффективный способ сделать это

DECLARE @Spend DECIMAL(18,2) = 1200.70


DECLARE @Extract TABLE (rowId int primary key, Mnth int, Amount Decimal )

insert INTO @Extract SELECT  1, 9 , m9 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 2, 10 , m10 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 3, 11 , m11 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 4, 12 , m12 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 5, 1 , m1 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 6, 2 , m2 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 7, 3 , m3 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 8, 4 , m4 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 9, 5 , m5 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 10, 6 , m6 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 11, 7 , m7 FROM T1 WHERE sYear=2017
insert INTO @Extract SELECT 12, 8 , m8 FROM T1 WHERE sYear=2017

Declare @sMonth int = 10, @MaxRow int, @MinRow int

Declare @Res TABLE (rowid int, mth int, mName NVARCHAR(3), v decimal,  s decimal) 
INSERT INTO @Res
SELECT
    rowid, Mnth,'m'+ CAST(Mnth AS NVARCHAR(3)), Amount, 
    SUM(Amount) OVER (ORDER BY rowId RANGE UNBOUNDED PRECEDING)
  FROM @Extract --where Mnth >= @sMonth --OR Mnth< @sMonth





-- This one can be used if we use remaining budget from previous months !!-----------------------------

SELECT TOP(1) @MaxRow = rowid
FROM @Res WHERE (s >= @Spend) 
ORDER BY rowid , s Desc;


SELECT rowid, mth,mName, v, s
FROM @Res WHERE (rowid <= @MaxRow) 
ORDER BY rowid; 

---------------------------------------------------------------------------------------------------------------


-- This one only uses Budget from the specified month onward, regrdless if there is still money remaining in the Prev month-----------------

-- SELECT @MinRow = rowid
-- FROM @Extract WHERE (Mnth = @sMonth) 

-- SELECT TOP(1) @MaxRow= rowid
-- FROM @Res WHERE (s >= @Spend) 
-- ORDER BY rowid,s  Desc;


-- SELECT rowid, mth, v, s
-- FROM @Res WHERE (rowid >= @MinRow )AND (rowid <= @MaxRow)
-- ORDER BY rowid; 

--------------------------------------------------------------------------------------------------------------------------------------------------------




-- Loop & Update ------------------------------------------------------------------------------------------------------------
Declare @rid INT = (SELECT MIN(rowid) FROM @Res), @Diff decimal(18,2), @sqlX   NVARCHAR(1000), @colName AS nVARCHAR(3);

while @rid is not null
begin

   SELECT @colName = mName , @Diff = CASE WHEN s <= @Spend THEN 0 ELSE (s- @Spend ) end FROM @Res where rowid = @rid

   -- PRINT @colName
   -- PRINT @Diff

   SELECT @sqlX = 'Update T1 SET T1.[' + @colName + '] = ' + CAST(@Diff AS NVARCHAR(max)) + ' where sYear = 2017 '



  -- PRINT @sqlX

 EXEC sp_executesql @sqlX


    select @rid = min( rowid ) FROM @Res where rowid > @rid AND (rowid <= @MaxRow) 
end



SELECT * FROM T1
...