Убрать систематическую ошибку из месячных итогов - PullRequest
0 голосов
/ 03 февраля 2010

Для того чтобы убрать смещение, представленное различиями в количестве дней в месяцах и годах (в случае високосных лет), из ежемесячных итоговых сравнений произвольных величин и предполагая, например, таблицу с именем My_Table со столбцом datetime с именем order_date и целым числом с именем revenue я использую следующий запрос для получения несмещенной суммы ежемесячного дохода:

-- sum revenue per month, divided by the number of days of that month 
-- and then multiplied by the average days of the that year's months 

SELECT datepart(mm,order_date) as my_month, sum(
round(convert(decimal, revenue) /
    CASE WHEN MONTH(order_date) = 2 THEN
CASE WHEN (YEAR(order_date) % 4 = 0 AND YEAR(order_date) % 100 != 0) OR 
          (YEAR(order_date) % 400  = 0) THEN 29 ELSE 28 END
     WHEN (MONTH(order_date)%8 + floor(MONTH(order_date)/8)) % 2 = 0 THEN 30 ELSE 31 END
    * CASE WHEN (YEAR(order_date) % 4 = 0 AND YEAR(order_date) % 100 != 0) OR 
                (YEAR(order_date) % 400  = 0) THEN 366 ELSE 365 END / 12 , 3)
) as monthly_unb_revenue 
FROM My_Table
group by datepart(mm,order_date)

Мне бы хотелось ваше мнение или другие практики

Ответы [ 2 ]

1 голос
/ 03 февраля 2010

Прокручивать собственные расчеты календаря может быть сложно. Вероятно, более надежно использовать встроенные функции.

Например, вы можете найти первый день любого месяца, например:

DATEADD(mm, DATEDIFF(m,0,DateColumn),0)

Выполнение datediff между ними даст вам количество дней в этом месяце. Вы могли бы сделать то же самое в течение многих лет:

select 
    datediff(d,
        DATEADD(mm, DATEDIFF(mm,0,getdate()),0),
        DATEADD(mm, DATEDIFF(mm,0,getdate())+1,0)) 
        as NumOfDaysThisMonth,
    datediff(d,
        DATEADD(yy, DATEDIFF(yy,0,getdate()),0),
        DATEADD(yy, DATEDIFF(yy,0,getdate())+1,0)) 
        as NumOfDaysThisYear

Этот пример работает на SQL Server, надеюсь, есть эквивалент на Sybase:)

0 голосов
/ 03 февраля 2010

Я предполагаю, что вы используете SQL Server, так как это единственная система, которую я знаю с datepart ().

В oracle и MySQL у вас есть функция LAST_DAY (). Я нашел пользовательский эквивалент функции для SQL Server здесь :

CREATE FUNCTION [dbo].[ufn_GetLastDayOfMonth] ( @pInputDate    DATETIME )
RETURNS DATETIME
BEGIN

    DECLARE @vOutputDate        DATETIME

    SET @vOutputDate = CAST(YEAR(@pInputDate) AS VARCHAR(4)) + '/' + 
                       CAST(MONTH(@pInputDate) AS VARCHAR(2)) + '/01'
    SET @vOutputDate = DATEADD(DD, -1, DATEADD(M, 1, @vOutputDate))

    RETURN @vOutputDate

END 
GO

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

...