Как разбить ежемесячный бюджет на каждый день SQL Server 2012 - PullRequest
0 голосов
/ 03 января 2019
DECLARE @TempTable TABLE 
            (
                Amount MONEY, 
                InsurType VARCHAR(100), 
                MonthNumber INT, 
                PostDate DATETIME, 
                DaysInMonth INT
            )

INSERT INTO @TempTable 
VALUES (2019317, 'Commercial Auto', 1, '2018-01-01 00:00:00.000', 31),
       (3757832, 'Commercial Auto', 2, '2018-01-01 00:00:00.000', 28),
       (5010746, 'Commercial Auto', 3, '2018-01-01 00:00:00.000', 31),
       (4461429.66, 'Commercial Auto', 4, '2018-01-01 00:00:00.000', 30),
       (4049404.44, 'Commercial Auto', 5, '2018-01-01 00:00:00.000', 31)

SELECT * FROM @TempTable 

Результат выглядит так:

enter image description here

Можно ли разбить сумму на каждый день месяца за все 5 месяцев??

Например, Amount для MonthNumber 1 = 2 019 317 долл. США / 31 = 65 139 долл. США в день.

Вывод должен выглядеть следующим образом:

enter image description here

Ответы [ 6 ]

0 голосов
/ 04 января 2019

Мне интересно, почему вы храните номер месяца и дни в месяце?Вы можете определить это достаточно просто, используя SQL:

DECLARE @Nums TABLE(num int)

;WITH nums AS
   (SELECT 1 AS value
    UNION ALL
    SELECT value + 1 AS value
    FROM nums
    WHERE nums.value <= 31)
insert @Nums
SELECT *
FROM nums

DECLARE @TempTable TABLE 
            (
                Amount MONEY, 
                InsurType VARCHAR(100), 
                PostDate DATETIME
            )

INSERT INTO @TempTable 
VALUES (2019317, 'Commercial Auto A', '2018-01-01 00:00:00.000'),
       (3757832, 'Commercial Auto B', '2018-02-01 00:00:00.000'),
       (5010746, 'Commercial Auto C', '2018-03-01 00:00:00.000'),
       (4461429.66, 'Commercial Auto D', '2018-04-01 00:00:00.000'),
       (4049404.44, 'Commercial Auto E', '2018-05-01 00:00:00.000')

SELECT (Amount / DAY(EOMONTH(PostDate))) as DailyAmount, InsurType, 
    datepart(month, PostDate) as TheMonth, n.num as TheDay
FROM @TempTable tt
    JOIN @Nums n ON n.num <= DAY(EOMONTH(PostDate))
ORDER BY datepart(month, PostDate)
0 голосов
/ 04 января 2019

Еще одна опция таблицы подсчета (с использованием MS SQL Server 2016)
Чтобы получить этот результат:

enter image description here
Это код:

;with TempTable AS(
SELECT
2019317 AS Amount, 'Commercial Auto' AS InsurType, 1 AS MonthNumber, '2018-01-01 00:00:00.000' AS PostDate, 31 AS DaysInMonth
UNION ALL SELECT 3757832, 'Commercial Auto', 2, '2018-01-01 00:00:00.000', 28
UNION ALL SELECT 5010746, 'Commercial Auto', 3, '2018-01-01 00:00:00.000', 31
UNION ALL SELECT 4461429.66, 'Commercial Auto', 4, '2018-01-01 00:00:00.000', 30
UNION ALL SELECT 4049404.44, 'Commercial Auto', 5, '2018-01-01 00:00:00.000', 31
)

,Tally AS(
SELECT top 31
    rn = Row_number() OVER(ORDER BY (SELECT NULL))
FROM sys.objects
)

SELECT
    TempTable.*,
    rn AS DayNum,
    MonthlyAmount           = round(cast(TempTable.amount / TempTable.DaysInMonth as money), 0)

FROM TempTable
    cross join Tally

where 
DaysInMonth = rn
--rn <= DaysInMonth

Order by MonthNumber, rn


Чтобы получить этот другой результат:

enter image description here


Это код:

 ;with TempTable AS(
    SELECT
    2019317 AS Amount, 'Commercial Auto' AS InsurType, 1 AS MonthNumber, '2018-01-01 00:00:00.000' AS PostDate, 31 AS DaysInMonth
    UNION ALL SELECT 3757832, 'Commercial Auto', 2, '2018-01-01 00:00:00.000', 28
    UNION ALL SELECT 5010746, 'Commercial Auto', 3, '2018-01-01 00:00:00.000', 31
    UNION ALL SELECT 4461429.66, 'Commercial Auto', 4, '2018-01-01 00:00:00.000', 30
    UNION ALL SELECT 4049404.44, 'Commercial Auto', 5, '2018-01-01 00:00:00.000', 31
    )

,Tally AS(
SELECT top 31
    rn = Row_number() OVER(ORDER BY (SELECT NULL))
FROM sys.objects
)

SELECT
    TempTable.*,
    rn AS DayNum,
    MonthlyAmount           = round(cast(TempTable.amount / TempTable.DaysInMonth as money), 0)

FROM TempTable
    cross join Tally



 where 
    --DaysInMonth = rn
    rn <= DaysInMonth

    Order by MonthNumber, rn
0 голосов
/ 03 января 2019

Существует системная таблица значений статических чисел для использования.Бросив этот ответ в смесь, подбери свой яд.

select number from master..spt_values d
where d.type = 'p'
and d.number between 1 and 31

select Amount/cast(DaysInMonth as money) DailyAmt,  InsurType, MonthNumber, d.number Day
from @TempTable t
join master..spt_values d on d.number <= t.DaysInMonth
and d.number between 1 and 31
0 голосов
/ 03 января 2019

С таблицей подсчета в качестве дополнительной опции для конструктора таблицы.

create table #TempTable  
            (
            Amount Money, 
            InsurType varchar(100), 
            MonthNumber int, 
            PostDate datetime, 
            DaysInMonth int
            )
        INSERT INTO #TempTable values (2019317,'Commercial Auto', 1, '2018-01-01 00:00:00.000',31 ),
                                        (3757832,'Commercial Auto', 2, '2018-01-01 00:00:00.000',28 ),
                                        (5010746,'Commercial Auto', 3, '2018-01-01 00:00:00.000',31 ),
                                        (4461429.66,'Commercial Auto', 4, '2018-01-01 00:00:00.000',30 ),
                                        (4049404.44,'Commercial Auto', 5, '2018-01-01 00:00:00.000',31 )


;WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b),
    cteTally(N) AS ( SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2)



select * 
from #TempTable t 
inner join cteTally on cteTally.N <= t.DaysInMonth
order by Amount, N

drop table #TempTable
0 голосов
/ 03 января 2019

Просто внутреннее соединение с (VALUES (1), ..., (31)).Вы не можете иметь более 31 дня в месяце, поэтому их легче набирать.

SELECT Amount / DaysInMonth, InsurType, MonthNumber, days.d
FROM @TempTable
INNER JOIN (VALUES
    (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15), (16), (17), (18), (19), (20), (21), (22), (23), (24), (25), (26), (27), (28), (29), (30), (31)
) AS days(d) ON days.d <= DaysInMonth
0 голосов
/ 03 января 2019

Это довольно легко на самом деле.Просто присоединитесь к таблице чисел, где число равно или меньше количества дней в месяце, а сумма - это просто сумма, деленная на количество дней.

...