【发布时间】:2021-06-06 19:19:40
【问题描述】:
我有一个 Access 查询 (qr1),它返回以下数据:
| dateField | stringField1 | stringField2 | booleanField |
|---|---|---|---|
| 11/09/20 17:15 | John | Nick | 0 |
| 12/09/20 17:00 | John | Mary | -1 |
| 13/09/20 17:30 | Ann | John | 0 |
| 13/09/20 19:30 | Kate | Alan | 0 |
| 19/09/20 19:30 | Ann | Missy | 0 |
| 20/09/20 17:15 | Jim | George | 0 |
| 20/09/20 19:30 | John | Nick | 0 |
| 27/09/20 15:00 | John | Mary | -1 |
| 27/09/20 17:00 | Ann | John | -1 |
| 27/09/20 19:30 | Kate | Alan | 0 |
| 28/09/20 18:30 | Ann | Missy | -1 |
| 03/10/20 18:30 | Jim | George | -1 |
| 04/10/20 15:00 | John | Nick | 0 |
| 04/10/20 17:15 | John | Mary | 0 |
| 04/10/20 20:45 | Ann | John | 0 |
| 05/10/20 18:30 | Kate | Alan | 0 |
| 17/10/20 15:00 | Jim | George | 0 |
| 17/10/20 17:15 | John | Nick | 0 |
| 18/10/20 15:00 | John | Mary | -1 |
| 18/10/20 17:15 | Ann | John | 0 |
注意事项:
- 字符串数据可以重复也可以不重复。
- 日期数据存储为字符串。我使用一个函数将其转换为日期。
Public Function STR2TIME(sTime As String) As Date
Dim arr() As String
sTime = Replace(sTime, ".", "/")
arr = Split(sTime, " ")
STR2TIME = DateValue(Format(arr(0), "dd/mm/yyyy")) + TimeValue(arr(1))
End Function
- qr1 按 STR2TIME(dateField) ASC 排序
现在我需要运行一个额外的查询来执行以下操作:
- 添加一个额外的列,其中:
- 计数记录直到是 (-1) 布尔字段
- 此后,从 1 开始重新计数
在这种情况下,输出应如下所示:
| dateField | stringField1 | stringField2 | booleanField | countField |
|---|---|---|---|---|
| 11/09/20 17:15 | John | Nick | 0 | 1 |
| 12/09/20 17:00 | John | Mary | -1 | 2 |
| 13/09/20 17:30 | Ann | John | 0 | 1 |
| 13/09/20 19:30 | Kate | Alan | 0 | 2 |
| 19/09/20 19:30 | Ann | Missy | 0 | 3 |
| 20/09/20 17:15 | Jim | George | 0 | 4 |
| 20/09/20 19:30 | John | Nick | 0 | 5 |
| 27/09/20 15:00 | John | Mary | -1 | 6 |
| 27/09/20 17:00 | Ann | John | -1 | 1 |
| 27/09/20 19:30 | Kate | Alan | 0 | 1 |
| 28/09/20 18:30 | Ann | Missy | -1 | 2 |
| 03/10/20 18:30 | Jim | George | -1 | 1 |
| 04/10/20 15:00 | John | Nick | 0 | 1 |
| 04/10/20 17:15 | John | Mary | 0 | 2 |
| 04/10/20 20:45 | Ann | John | 0 | 3 |
| 05/10/20 18:30 | Kate | Alan | 0 | 4 |
| 17/10/20 15:00 | Jim | George | 0 | 5 |
| 17/10/20 17:15 | John | Nick | 0 | 6 |
| 18/10/20 15:00 | John | Mary | -1 | 7 |
| 18/10/20 17:15 | Ann | John | 0 | 1 |
问题
我尝试了很多方法,结果都是错误的。
最后我认为计算从当前日期到前一个日期的零(比当前最大和更小)可以解决问题:
SELECT t.*, (SELECT COUNT(*)
FROM qr1 tt
WHERE booleanField = 0
AND STR2TIME(tt.dateField) >= (SELECT TOP 1 dateField
FROM qr1
WHERE booleanField = -1
AND STR2TIME(dateField) < STR2TIME(t.dateField)
ORDER BY STR2TIME(dateField) DESC
)
AND STR2TIME(tt.dateField) <= STR2TIME(t.dateField)
) AS CountMatches
FROM qr1 t;
但在 countField 上仍然给我错误的数字结果:
| countField |
|---|
| 0 |
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 1 |
| 2 |
| 3 |
| 1 |
| 12 |
| 13 |
| 14 |
| 15 |
| 16 |
| 17 |
| 18 |
| 13 |
我做错了什么?我无法得到它。如何得到想要的结果?
编辑:
我将根据@Gordon Linoff 和@Gustav 的回答发布最终代码,稍微简化。
变化说明:
- 我在这一步去掉了转换功能。我不是在每条记录中转换 7 次 *,而是在第一个查询中只转换一次,在这里可以比较值。
- 我省略了检查零,因为没有必要。
- 我添加了 NZ 函数以在内部子查询返回 NULL 时获取值。那是当没有任何“是”时,可以从较小的日期开始计算(通常是第一条记录)。
- 剩下的唯一问题是,对于 NZ,我得到的值比我需要的少 1,所以我在 dateField 中添加了 -1 以增加 1。
代码如下:
SELECT t.*, (SELECT COUNT(*) FROM qr2 tt
WHERE tt.dateField <= t.dateField
AND tt.dateField > NZ((SELECT TOP 1 dateField FROM qr2
WHERE booleanField = True
AND dateField < t.dateField
ORDER BY dateField DESC
), tt.dateField - 1)
) AS CountMatches
FROM qr2 AS t;
【问题讨论】:
-
MS Access 是这种类型的数据操作的错误数据库。我的建议是你升级。