我不太确定这个术语是什么,我一直称它为“Split Weeks”,但这是我需要找到的。
假设:
用户将输入@StartDate
和@EndDate
col_week_end_date
将始终在星期六结束,并且是DateTime列。
我希望循环多个月或一个月,并总结col_payment_amt
使用2010年9月的月份,col_payment_amt
col_week_end_date
落在09/04/2010,涵盖8月29日至9月4日这一周。
付款月份是九月,但本周(周三,周四,周五)只有3个工作日。因此,该周只支付了3/5的款项。
同样的事情发生在一个月末。在这种情况下,col_week_end_date
将于2010年2月10日发布。本周仅支付4/5的款项。
我有一种特殊的方法可以在一个月初和最后发生这种情况时对col_payment_amt
求和。
我无法弄清楚的是如何告诉我何时在一个月的开始,当我在一个月结束时所以我可以应用适当的功能,在运行报告时多个月(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...
我正试图弄清楚月末和月底部分。我有其他部分。
答案 0 :(得分:2)
此代码适用于IBM Informix Dynamic Server(在11.50.FC6上针对MacOS X 1.06.4进行了测试,但适用于任何受支持的IDS版本以及任何平台)。您需要转换为MS SQL Server表示法。
CREATE FUNCTION NumWeekDaysInRefMonth(eow DATE DEFAULT TODAY, ref_month INTEGER)
RETURNING INT AS numdays;
DEFINE monday DATE;
DEFINE friday DATE;
DEFINE mon_month INTEGER;
DEFINE fri_month INTEGER;
IF eow IS NULL OR ref_month IS NULL THEN RETURN NULL; END IF;
LET monday = eow - WEEKDAY(eow) + 1;
LET friday = monday + 4;
LET mon_month = MONTH(monday);
LET fri_month = MONTH(friday);
IF mon_month = ref_month AND fri_month = ref_month THEN
-- All in same month: 5 days count.
RETURN 5;
END IF;
IF mon_month != ref_month AND fri_month != ref_month 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 mon_month = ref_month THEN
-- End of month
RETURN 5 - DAY(friday);
ELSE
-- Start of month
RETURN DAY(friday);
END IF;
END FUNCTION;
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;
Informix DATE类型以天为单位进行计数,因此在DATE中添加1即可获得后一天。 Informix WEEKDAY函数返回0表示星期日,1表示星期一,...,5表示星期五,6表示星期六。 DAY,MONTH和YEAR函数返回DATE值的相应分量。
该代码允许将一周中的任何一天作为付款的参考日期(它不必是星期六)。同样,虽然版本1的示例使用月中的第一天作为月份的参考日,但您可以提供必要月份内的任何日期作为参考日期;在版本2中,简化为传递必需的月份数。
如果有人将NULL传递给函数,则答案为NULL。
然后我们计算包含“周末”日期的星期一;如果工作日是星期日,则减去0并加1以获得星期一;如果工作日是星期六,它减去6并加1以获得星期一;周五是4天后。
在版本1中,我们计算年和月的表示。
如果周一和周五都在参考月份,那么答案是5天;如果两者都没有落入参考月份,答案是0天。如果星期五在参考月份内,则星期五日期的DAY()值是该月份的天数。否则,星期一在参考月份内,并且该月份的天数是5天(星期五)。
请注意,此计算涉及完全无关的月份 - 如最后一个测试用例所示; 10月付款的零天应该在8月份计算。
答案 1 :(得分:1)
好的,这就是我最终做的事情。
我设置了一个WHILE循环。我遍历日期范围的月份,并将数据插入TempTable以及数字引用月份列(嗯,实际上是INT)和月份名称(9月,10月等...)。然后从TempTable I中选择数据并使用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
到目前为止,由于我拥有的数据量有限,它似乎与我可用的月份中的分周数一起工作。似乎“参考月”是关键,我需要循环并将数据放入TempTable中。我希望有一种方法可以在一次传递中获得它,或者至少快速转储到#TempTable并从中进行选择。
我不确定它的效率如何,但它只适用于月度报告,而不是真正的在线互动报告。