如何按每日SQL Server 2012打破每月预算

时间:2019-01-03 20:24:58

标签: sql-server tsql sql-server-2012

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的{​​{1}} = = $ 2,019,317 / 31 =每天$ 65,139。

输出应如下所示:

enter image description here

6 个答案:

答案 0 :(得分:1)

真的很容易。只需加入一个等于或小于一个月中天数的数字表,金额就是总数除以天数。

答案 1 :(得分:1)

只需与(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

答案 2 :(得分:0)

使用计数表作为表构造函数的附加选项。

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

答案 3 :(得分:0)

存在一个要使用的静态数值系统表。把这个答案扔进去,选择你的毒药。

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

答案 4 :(得分:0)

另一个提示表选项(使用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

答案 5 :(得分:0)

我想知道为什么您要存储月份数和月份中的天?您可以使用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)