在MS Access DB中,我有关于客户的到达和离开日期的信息。基于此,我想计算每周访问的客户数量。
考虑下面的例子。彼得在1月的第一周到达并在第三周离开(周日从周日开始)。另一方面,玛丽在第一周到达并离开。
我希望输出如下所示,第一列中的周数和第二列中的总访客数。
请达到这个目标的最佳方式是什么?
我的解决方案采用德国日期格式,使用ORACLE进行测试。我每周都会建立一些日历表(tw_test_week)来加入它。
CREATE TABLE tw_test_client (
client VARCHAR2(10),
arrival DATE,
departure DATE
);
INSERT INTO tw_test_client VALUES
( 'Peter', to_date('01.01.2018','DD.MM.YYYY'), to_date('11.01.2018','DD.MM.YYYY'));
INSERT INTO tw_test_client VALUES
( 'Mary', to_date('01.01.2018','DD.MM.YYYY'), to_date('01.02.2018','DD.MM.YYYY'));
CREATE TABLE tw_test_week (
weekid INT,
started DATE,
ended DATE
);
INSERT INTO tw_test_week VALUES
( to_char(to_date('01.01.2018','DD.MM.YYYY'),'WW'),
to_date('01.01.2018','DD.MM.YYYY'),
to_date('07.01.2018','DD.MM.YYYY')
);
INSERT INTO tw_test_week VALUES
( to_char(to_date('08.01.2018','DD.MM.YYYY'),'WW'),
to_date('08.01.2018','DD.MM.YYYY'),
to_date('14.01.2018','DD.MM.YYYY')
);
INSERT INTO tw_test_week VALUES
( to_char(to_date('15.01.2018','DD.MM.YYYY'),'WW'),
to_date('15.01.2018','DD.MM.YYYY'),
to_date('21.01.2018','DD.MM.YYYY')
);
INSERT INTO tw_test_week VALUES
( to_char(to_date('22.01.2018','DD.MM.YYYY'),'WW'),
to_date('22.01.2018','DD.MM.YYYY'),
to_date('28.01.2018','DD.MM.YYYY')
);
INSERT INTO tw_test_week VALUES
( to_char(to_date('29.01.2018','DD.MM.YYYY'),'WW'),
to_date('29.01.2018','DD.MM.YYYY'),
to_date('04.02.2018','DD.MM.YYYY')
);
SELECT w.weekid, COUNT(*)
FROM tw_test_week w
JOIN tw_test_client c
ON w.started BETWEEN c.arrival and c.departure
GROUP BY w.weekid
ORDER BY w.weekid;
结果
WEEKID COUNT
1 2
2 2
3 1
4 1
5 1
创建一个包含数字1到53的表。我的查询中的这个表名为WeekNumTable
,包含一个列出每周编号的字段。
SELECT WeekNum
, COUNT(WeekNum) AS TotalClients
FROM WeekNumTable INNER JOIN ClientTable ON
WeekNumTable.WeekNum>=DatePart("ww",ClientTable.Arrival-Weekday(ClientTable.Arrival,1)+7) AND
WeekNumTable.WeekNum<=DatePart("ww",ClientTable.Departure-Weekday(ClientTable.Departure,1)+7)
GROUP BY WeekNum
你的例子让我感到困惑,因为你将第3周列为拥有1个客户端,而数据表却没有。
编辑:我可以看到的一个问题是,如果你确实想看看接下来的100周,那么你需要将这些年份分开来,否则第1周与这两年相比将会被混为一谈。
您可以使用一系列查询来获取此信息。
首先,创建一个名为Ten的查询:
SELECT DISTINCT Abs([id] Mod 10) AS N
FROM MSysObjects;
然后,您可以创建一个查询ClientDays,列出您在首次到达和最近出发之间的所有日期:
SELECT DISTINCT
[Ten_0].[N]+[Ten_1].[N]*10+[Ten_2].[N]*100 AS Id,
DateAdd("d",[Ten_0].[N]+[Ten_1].[N]*10+[Ten_2].[N]*100,[StartDate]) AS [Date]
FROM
Ten AS Ten_0,
Ten AS Ten_1,
Ten AS Ten_2,
(Select
Min([Arrival]) As StartDate,
DateDiff("d", Min([Arrival]), Max([Departure])) As Days
From
ClientDates) AS T
WHERE
((([Ten_0].[N]+[Ten_1].[N]*10+[Ten_2].[N]*100)<=[Days])
AND
((Ten_0.N)<=[Days]\1)
AND
((Ten_1.N)<=[Days]\10)
AND
((Ten_2.N)<=[Days]\100));
在ClientWeeks的查询中使用它来查找周数:
SELECT
Year([Date]) AS [Year],
DatePart("ww",[Date]) AS Week,
ClientDates.Client
FROM
ClientDays,
ClientDates
WHERE
ClientDays.Date Between [Arrival] And [Departure]
GROUP BY
Year([Date]),
DatePart("ww",[Date]),
ClientDates.Client;
最后,计算客户:
SELECT
ClientWeeks.Year,
ClientWeeks.Week,
Count(ClientWeeks.Client) AS TotalClients
FROM
ClientWeeks
GROUP BY
ClientWeeks.Year,
ClientWeeks.Week;
请注意,由于您打算使用不一致的周编号方法,因此您将难以计算新年。
唯一明确的周数是yyyy-ww的ISO-8601系统,因为第一周和/或上周将跨越日历年的边界。
如果您希望实现此功能,请留言,因为无法使用本机VBA功能完成此操作;必须使用自定义函数,但如果您不使用它们,我不希望在此处发布它们。