开发者

SQL Server 2008 information per month divided onto days

开发者 https://www.devze.com 2023-03-17 19:39 出处:网络
I have a table that has \"periods\" and looks like this (added some rows as example): StartDate | EndDate| Amount1 |Amount2 | Type

I have a table that has "periods" and looks like this (added some rows as example):

          | StartDate | EndDate  | Amount1 |   Amount2 | Type
==============================================================
1         |  20110101 | 20110131 |      89 |      2259 |    1
2         |  20110201 | 20110228 |     103 |     50202 |    1
3         |  20110301 | 20110331 |      90 |     98044 |    1
4         |  20110401 | 20110430 |      78 |    352392 |    1
==============================================================

As you can see each "period" is exactly one month. Each month is represented four times (there are 4 types) so this table has 48 rows.

I have a selection that gives me the number of days per period (simply, the day out of the EndDate, since its always the amount of days in that period) and Amount1PerDay and Amount2PerDay (the amount of that period divided by the number of days).

The first problem is:

I need a View on this table that shows me one row for each day in every period with the Amount1 and Amount2 columns that hold the value of that period divided by the number of days in that period.

The second problem is:

Most of these divisions do not give me a whole number. Decimals are not an option, so I need to divide the remaining days (after division) among the first开发者_开发百科 days of that period. Take January as an example: Amount1 has 89. Divided over 31 days thats almost 2,9. So its 2 per day, and the first 27 days get 3 (,9 * 31 = 27). That way the result has only whole numbers in it.


Assuming StartDate and EndDate are of type date or datetime, and Amount1 & Amount2 are integers:

SELECT
  Date,
  Amount1 = Amount1Whole + CASE WHEN DayNum < Amount1Rem THEN 1 ELSE 0 END,
  Amount2 = Amount2Whole + CASE WHEN DayNum < Amount2Rem THEN 1 ELSE 0 END,
  Type
FROM (
  SELECT
    Date         = DATEADD(day, v.number, t.StartDate),
    DayNum       = v.number,
    Amount1Whole = Amount1 / DAY(t.EndDate),
    Amount2Whole = Amount2 / DAY(t.EndDate),
    Amount1Rem   = Amount1 % DAY(t.EndDate),
    Amount2Rem   = Amount2 % DAY(t.EndDate),
    t.Type
  FROM atable t
    INNER JOIN master..spt_values v ON v.type = 'P'
      AND v.number BETWEEN 0 AND DATEDIFF(day, t.StartDate, t.EndDate)
) s

SQL Server performs integer division when both operands are integers, so, for instance, the result of 5 / 2 would be 2, and not 2.5.

master..spt_values is a long-existing system table used for internal purposes. It contains a subset of rows that you can use as a number (tally) table, which is what it serves as in this query.


Q1

How to select a range of dates is explained in this article: http://social.msdn.microsoft.com/forums/en-US/sqlexpress/thread/916161f2-cf3c-4b6b-9015-9d13ed1af49e/

This should produce a column named THEDATE to be used for Q2

Q2

How to select the distributed amount goes like: SELECT FLOOR(AMOUNT / NUMDAYS) + IIF( DAY(THEDATE) <= (AMOUNT - NUMDAYS * FLOOR(AMOUNT / NUMDAYS) ), 1, 0)

NUMDAYS = DATEDIFF( d, STARTDATE, ENDDATE ) + 1

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号