Sql server 2005 确定如何在SQL Server中计算拆分周

Sql server 2005 确定如何在SQL Server中计算拆分周,sql-server-2005,datetime,Sql Server 2005,Datetime,我不太清楚这个词是什么,我一直称之为分裂周,但这里是我需要了解的 鉴于: 用户将输入@StartDate和@EndDate col_week_end_date将始终在周六结束,并且是DateTime列 我想循环使用多个月或一个月,并计算COLU付款金额 使用2010年9月,列账周结束日期为2010年4月9日的列账付款金额,涵盖8月29日至9月4日这一周 付款月份为9月,但本周只有3个工作日,即周三、周四、周五。因此,该周只支付了三分之五的款项 同样的事情也会在一个月结束时发生。在这种情况下,co

我不太清楚这个词是什么,我一直称之为分裂周,但这里是我需要了解的

鉴于:

用户将输入@StartDate和@EndDate

col_week_end_date将始终在周六结束,并且是DateTime列

我想循环使用多个月或一个月,并计算COLU付款金额

使用2010年9月,列账周结束日期为2010年4月9日的列账付款金额,涵盖8月29日至9月4日这一周

付款月份为9月,但本周只有3个工作日,即周三、周四、周五。因此,该周只支付了三分之五的款项

同样的事情也会在一个月结束时发生。在这种情况下,col_week_end_日期为2010年2月10日。本周只支付四分之五的款项

我有一种特殊的方法来计算月初和月末的col_付款金额

我搞不清楚的是,在8月至10月期间运行多个月的报告时,如何判断我何时在一个月的开始,何时在一个月的结束,以便应用适当的功能

目前,如果我只是强迫他们运行一个月的报告,没有问题,而且我被告知这只是一个月的报告,但我知道最终我会被问到它是否可以运行多个月

我知道基本上是这样的:

SELECT sum(CASE WHEN at-top-of-month-with-split-week THEN....
                WHEN at-bottom-of-month-with-split-week THEN...
                ELSE col_payment_amt END) as PayTotal
FROM...
WHERE....
GROUP BY...

我正试图找出月底和月顶的部分。我还有其他部分。

好的,简而言之,这里是我最后要做的

我设置了一个WHILE循环。我循环查看日期范围的月份,并将数据插入到一个诱人的列表中,以及一个数字参考月份列,实际上是一个整数,月份名称是九月、十月等等。。。。然后,我从表中选择数据,并有一个CASE语句来确定使用哪个计算。所以它读起来像这样

                -- Top of the month, Split Week
select sum(case when datepart(d,col_week_end_date) <= 7 AND RefMonth = month(col_ween_end_date)
                then ...Top of Month calc...

                -- Middle of the month, entire week is in Reference Month
                when datepart(d,col_week_end_date) > 7 AND RefMonth = month(col_week_end_date)
                then ...Just SUM the column as usual...

                -- Bottom of month, Split Week
                when RefMonth < month(col_week_end_date)
                then ...Bottom of Month calc...
          ) end as MonthlySum,
       col_RefMonth,
       col_RefMonthName
from dbo.TempTable
group by col_RefMonth, col_RefMonthName
order by col_RefMonth
到目前为止,由于我掌握的数据量有限,它似乎在处理我所掌握的月份中的几周。似乎参考月份是关键,我需要循环并将数据放在一个诱人的位置。我希望有一种方法可以在一次传球中得到它,或者至少可以快速地将球扔进一个诱人的场地,然后从中选择


我不确定它的效率有多高,但它只用于月度报告,而不是真正的在线交互式报告。

此代码在IBM Informix Dynamic Server中工作,该服务器在MacOS X 1.06.4的11.50.FC6上测试,但可以在任何受支持的IDS版本和任何平台上工作。您需要将其转换为MS SQL Server符号

版本2-仅通过月号标识的参考月 测试用例 这与下面的上一个版本的逻辑基本相同;只需要一个月的号码就可以确定您感兴趣的是哪个月,而不是一个完整的日期

第1版-完整参考日期 测试用例 这些测试等同于前一组测试

SELECT NumWeekDaysInRefMonth('2010-09-04', '2010-09-01') answer, 3 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-09-04', '2010-08-01') answer, 2 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-02', '2010-09-01') answer, 4 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-02', '2010-10-01') answer, 1 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-02', '2010-08-01') answer, 0 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-09', '2010-10-01') answer, 5 AS expected FROM dual;
解释 Informix日期类型以天为单位,因此将1添加到一个日期会给出第二天。Informix WEEKDAY函数返回0表示星期天,1表示星期一,…,5表示星期五,6表示星期六。日、月和年函数返回日期值的相应组成部分

代码允许一周中的任何一天作为付款的参考日期,而不必是星期六。同样,尽管版本1的示例使用月的第一天作为该月的参考日,但您可以提供所需月份内的任何日期作为参考日;在版本2中,这被简化为传递必需的月数

如果有人将NULL传递给函数,则答案为NULL

然后我们计算一周中包含“周末”日期的星期一;如果星期天是星期天,则减去0,再加1得到星期一;如果星期天是星期一,它减去6加1得到星期一;等。星期五是4天后

在版本1中,我们计算年份和月份的表示形式

如果星期一和星期五都在参考月份,那么答案是5天;如果两者都不在参考月内,则答案为0天。如果星期五在参考月内,则星期五日期的日值为该月的天数。否则,星期一在参考月内,该月的天数为5天星期五


请注意,此计算涉及完全不相关的月份-如最后一个测试用例所示;10月支付的款项中有零天应在8月计算。

如果你想在多个月内得到一笔款项,你可能只需要检查哪个月,只关心你是在检查的第一个月的开始还是最后一个月的结束。我遗漏了什么吗?代码可能太复杂了,我会
ld考虑创建一个存储过程函数来进行计算。我可能会将其设计为两个参数:一个参数将确定年份和月份,另一个参数将确定周末。返回值将是可能值为0.0、0.2、0.4、0.6、0.8、1.0的“实”值,或者是范围为0..5的整数。对于其余部分,这是一个正确操作MS SQL Server的日期/时间函数的问题。然后,您可以使用SUMsplit_weekref_date、col_payment_date*col_payment_amt或该主题的变体。@Andrew,如果有9月至10月的日期范围,我必须知道分割周的钱放在哪里。截止到10月2日的一周,该周资金的4/5需要在9月份入账,例如10月份的1/5。我有计算月上/月底的公式,我只需要找出一种方法来选择何时进行每一项计算。@Jonathan一个函数可以工作,同样,函数需要返回或知道它是在月上还是月下。也许如果我分步执行,创建一个SP,将一些复杂的数据转储到一个诱人的文件中,然后处理这些数据。@D-Scott那么,输出中的列基本上是一个月吗,例如。,2010-09年度以及该月的SUMcol_付款金额,考虑到您已经设计好的月初和月底计算?看起来这是可行的,但是您有一个参考日期,这似乎是关键。例如,我知道特定付款的截止日期为2010年2月10日。从只知道那个日期开始,我试图找到一种方法来确定9月的总付款额,以及10月的总付款额,如果给定一个跨越两个月或两个多月的日期范围。如果只给我一个月的时间,我们很容易知道参考月份。我感谢你的帮助。我将使用这段代码,看看是否可以用它来简化我目前拥有的东西。@D斯科特:我不清楚为什么参考日期会有问题。你必须知道你对哪一个月感兴趣,当你要求9月份的总数与10月份的总数在这个界限上分开一周时。当然,这是我的看法。我的测试表明,当被问及9月份的部分时,你得到4分,10月份的部分得到1分,根据需要再加上5分。12月/1月分割需要参考日期的年份部分;白天的部分无关紧要。然而,你更了解你的数据,但我想你知道你是在寻找9月还是10月的账单信息。@Johnathan Leffler:你必须知道你对哪个月感兴趣,当你询问9月的账单和10月的账单时,你需要在这一边界上划分一周。这就是我想弄明白的。给定周末日期和日期范围,如何确定用哪种方法计算当月上下两个月的工资。因此,鉴于SELECT的信息。。从…起其中col_week_end_date>='09/01/2010'和col_week_end_date所以我做了什么,使用WHILE循环首先运行日期范围,并将我需要的列,加上RefMonth和RefMonthName放入临时表中。然后在临时表上运行我的select,我无法确定我工作的月份,也无法在参考月份的顶部/底部正确计算付款。我唯一要说的是,如果您多次写出该代码,您将面临维护噩梦。如果这是唯一需要计算的语句,那么很好。如果没有-使用一个函数。目前还不确定,实际上我刚刚发现我甚至不需要担心分裂周。现在他们只想数一数当月的付款。我认为,由于整个系统仍处于开发阶段,最简单的答案是只添加一个参考月列。然后,不需要通过循环数据来计算,只需再循环一次就可以得到总和。
SELECT NumWeekDaysInRefMonth('2010-09-04',  9) answer, 3 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-09-04',  8) answer, 2 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-02',  9) answer, 4 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-02', 10) answer, 1 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-02',  8) answer, 0 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-09', 10) answer, 5 AS expected FROM dual;
CREATE FUNCTION NumWeekDaysInRefMonth(eow DATE DEFAULT TODAY, ref DATE DEFAULT TODAY)
    RETURNING INT AS numdays;
    DEFINE mon DATE;
    DEFINE fri DATE;
    DEFINE v_mon INTEGER;
    DEFINE v_fri INTEGER;
    DEFINE v_ref INTEGER;

    IF eow IS NULL OR ref IS NULL THEN RETURN NULL; END IF;

    LET mon = eow - WEEKDAY(eow) + 1;
    LET fri = mon + 4;
    LET v_mon = YEAR(mon) * 100 + MONTH(mon);
    LET v_fri = YEAR(fri) * 100 + MONTH(fri);
    LET v_ref = YEAR(ref) * 100 + MONTH(ref);

    IF v_mon = v_ref AND v_fri = v_ref THEN
        -- All in same month: 5 days count.
        RETURN 5;
    END IF;
    IF v_mon != v_ref AND v_fri != v_ref THEN
        -- None in the same month: 0 days count.
        RETURN 0;
    END IF;
    -- Some of the days are in the same month, some are not.
    IF v_mon = v_ref THEN
        -- End of month
        RETURN 5 - DAY(fri);
    ELSE
        -- Start of month
        RETURN DAY(fri);
    END IF;

    -- Month-end wrapping
    -- 26 27 28 29 30 31  1  2  3  4  5  6  Jan, Mar, May, Jul, Aug, Oct, Dec
    -- 25 26 27 28 29 30  1  2  3  4  5  6  Apr, Jun, Sep, Nov
    -- 24 25 26 27 28 29  1  2  3  4  5  6  Feb - leap year
    -- 23 24 25 26 27 28  1  2  3  4  5  6  Feb
    -- Mo Tu We Th Fr Sa Su Mo Tu We Th Fr
    -- Su Mo Tu We Th Fr Sa Su Mo Tu We Tu
    -- Sa Su Mo Tu We Th Fr Sa Su Mo Tu We
    -- Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu
    -- Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo
    -- We Th Fr Sa Su Mo Tu We Th Fr Sa Su
    -- Tu We Th Fr Sa Su Mo Tu We Th Fr Sa

END FUNCTION;
SELECT NumWeekDaysInRefMonth('2010-09-04', '2010-09-01') answer, 3 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-09-04', '2010-08-01') answer, 2 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-02', '2010-09-01') answer, 4 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-02', '2010-10-01') answer, 1 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-02', '2010-08-01') answer, 0 AS expected FROM dual;
SELECT NumWeekDaysInRefMonth('2010-10-09', '2010-10-01') answer, 5 AS expected FROM dual;