在Access(SQL)中查找两个日期之间的连续和单个实例日期

时间:2017-04-05 10:54:54

标签: sql ms-access

早上好,

我想知道每个缺席的实例,其中一个实例是两个日期点之间的任何一天或一组连续天。我在原始问题中得到了大量的帮助,并且除了“两个日期之间”部分之外,还有一些工作代码。我希望有人可以帮助我将“两个日期”元素添加到工作代码中。

示例问题:
在2016年1月3日至2016年1月19日期间,每个人都有多少次缺席和总天数?

示例数据:

|IDRef  |RecordDate  |Racf  |Type  |LengthOfAbsence 
|1788  |04-Jan-16  |Bob  |Sickness |420
|1789  |04-Jan-16  |Jill  |Sickness |420 
|1790  |05-Jan-16  |Bob  |Sickness |420 
|1791  |17-Jan-16  |Jill|Sickness |420  
|1792  |18-Jan-16  |Bob  |Sickness |420   

预期产出:

| Racf  |Total Days  |Instances
|Bob  | 3  |2  
|Jill  |2  |2

工作代码:

SELECT Absence.Racf, Count(Absence.RecordDate) AS CountOfRecordDate
FROM Absence LEFT JOIN (select Racf, [RecordDate]+IIf(Weekday([RecordDate],7)=1,2,1) as RecordDate2 from Absence) AS t2 ON (Absence.RecordDate = t2.RecordDate2) AND (Absence.Racf = t2.Racf)
WHERE (((t2.RecordDate2) Is Null))
GROUP BY Absence.Racf;

我最近尝试将其修改为仅在两个日期之间查看(这不会导致错误但会返回意外/不正确的值):

Sql = "SELECT Absence.Racf, Count(Absence.RecordDate) AS CountOfRecordDate "
Sql = Sql & "FROM Absence LEFT JOIN (select Racf, [RecordDate]+IIf(Weekday([RecordDate],7)=1,2,1) as RecordDate2 from Absence where [RecordDate] BETWEEN #" & sFromDate & "# AND #" & sToDate & "#) AS t2 ON (Absence.RecordDate = t2.RecordDate2) AND (Absence.Racf = t2.Racf) "
Sql = Sql & "WHERE (((t2.RecordDate2) Is Null)) AND [t2.RecordDate2] BETWEEN #" & sFromDate & "# AND #" & sToDate & "# "
Sql = Sql & "GROUP BY Absence.Racf;"

原始问题:Count instances of consecutive dates for associated name (VBA, SQL)

对于这最后一步的任何帮助都将不胜感激,对其工作原理的解释也不会受到影响,因为我不知道!

2 个答案:

答案 0 :(得分:1)

这是我在Access中测试的新工作代码,但尚未在从Excel调用的宏中

SELECT Absence.Racf, Count(Absence.RecordDate) AS CountOfRecordDate, Absence.RecordDate
FROM Absence LEFT JOIN [select Racf, [RecordDate]+IIf(Weekday([RecordDate],7)=1,2,1) as RecordDate2 from Absence]. AS t2 ON (Absence.Racf = t2.Racf) AND (Absence.RecordDate = t2.RecordDate2)
WHERE (((t2.RecordDate2) Is Null))
GROUP BY Absence.Racf, Absence.RecordDate
HAVING (((Absence.RecordDate)>#1/1/2016# And (Absence.RecordDate)<#10/11/2016#));

日期范围在WHERE子句中不起作用的原因是此处的日期始终为NULL,因此您永远不会获得任何记录。

您同样可以使用BETWEEN语句而不是&gt;和&lt;。

对不起,这不是您正在寻找的整洁解决方案,但这超出了您在Access中的单个查询中可以轻松完成的任务。输出看起来像这样

enter image description here

我建议您做什么(如果您想为多个用户设想)是使用数据透视表来总结每个用户的结果。

但你也可以试试这个

SQL = "select racf, count(racf) AS Instances from ("
SQL = SQL & "SELECT Absence.Racf, Count(Absence.RecordDate) AS CountOfRecordDate,Absence.RecordDate"
SQL = SQL & " FROM (Absence LEFT JOIN (select Racf, RecordDate+IIf(Weekday([RecordDate],7)=1,2,1) as RecordDate1 from Absence) AS t1 ON (Absence.RecordDate = t1.RecordDate1) AND (Absence.Racf = t1.Racf))"
SQL = SQL & " WHERE ((t1.RecordDate1) Is Null) "
SQL = SQL & " GROUP BY Absence.Racf,Absence.RecordDate"
SQL = SQL & " HAVING (((Absence.RecordDate)>#1/1/2016# And (Absence.RecordDate)<#10/11/2016#))"
SQL = SQL & ") AS T0 GROUP BY RACF"

修改

我确信在反思中虽然正确,但这可以简化,因为内部GROUP BY不能用于任何有用的目的 - HAVING子句应该作为WHERE子句带到T0之外。

看起来应该是这样的

SQL = "select racf, count(racf) AS Instances from ("
SQL = SQL & "SELECT Absence.Racf, Absence.RecordDate"
SQL = SQL & " FROM (Absence LEFT JOIN (select Racf, RecordDate+IIf(Weekday([RecordDate],7)=1,2,1) as RecordDate1 from Absence) AS t1 ON (Absence.RecordDate = t1.RecordDate1) AND (Absence.Racf = t1.Racf))"
SQL = SQL & " WHERE ((t1.RecordDate1) Is Null) "
SQL = SQL & ") AS T0 WHERE (((RecordDate)>#1/1/2016# And (RecordDate)<#10/11/2016#))"
SQL = SQL & "GROUP BY RACF"

修改

现在已经对此进行了测试并确实有效,但#10/11/2016#之类的日期不明确 - 虽然我的地区是英国,但它似乎被解释为2016年10月11日。

建议使用

Datevalue(""10 November 2016"")

其中引号必须加倍,因为它们出现在带引号的字符串中。

答案 1 :(得分:1)

感谢汤姆的回答,我终于到了那里。

要在日期范围内检索单个或连续日期的实例,以下是有用的:

  • 创建了一个新表来保存所需的日期。
  • 运行Access中的查询,从Excel中将日期点之间所需的记录追加到新表中。
  • 从Excel运行“选择查询”以返回实例,不包括星期日。

从Excel运行查询(db已定义为OpenDatabase):

db.QueryDef.Execute

追加查询:

    INSERT INTO AbsenceInstances ( Racf, RecordDate )
    SELECT Absence.Racf, Absence.RecordDate
    FROM Absence
    WHERE ((Absence.RecordDate)>=#01/01/2017# And (Absence.RecordDate)<=#28/03/2017#);

选择查询:

Sql = "SELECT AbsenceInstances.Racf, Count(AbsenceInstances.RecordDate) AS CountOfRecordDate"
Sql = Sql & " FROM AbsenceInstances LEFT JOIN (select Racf, [RecordDate]+IIf(Weekday([RecordDate],7)=1,2,1) as RecordDate2 from AbsenceInstances) AS t2 ON (AbsenceInstances.RecordDate = t2.RecordDate2) AND (AbsenceInstances.Racf = t2.Racf)"
Sql = Sql & " WHERE (((t2.RecordDate2) Is Null))"
Sql = Sql & " GROUP BY AbsenceInstances.Racf;"

不能感谢汤姆的帮助。我希望这个总结在将来对其他任何人都有用。