访问SQL-连续失败数周

时间:2018-08-22 14:35:04

标签: sql ms-access access-vba

我在Access中有一个表,其中记录了每个人每天的测试结果。有些人可能在同一天参加了一项以上的考试。我在下面显示了此表的简化版本:

|  ID | testDate  |  Person   |   Pass? | ConsecFailDays |
----------------------------------------------------------
|  01 |  01/08/18 |  John     |  Fail   |                |
|  02 |  01/08/18 |  John     |  Pass   |                |
|  03 |  03/08/18 |  John     |  Fail   |                |
|  04 |  01/08/18 |  Mark     |  Fail   |                |
|  05 |  02/08/18 |  Mark     |  Pass   |                |

我尝试编写一个SQL UPDATE查询,该查询将使用该人至少一项测试未通过的连续天数来更新最后一列(不一定是连续的日历天,而是他们实际进行了测试的天数) 。最终结果应该像这样...

|  ID | testDate  |  Person   |   Pass? | ConsecFailDays |
----------------------------------------------------------
|  01 |  01/08/18 |  John     |  Fail   |       1        |
|  02 |  01/08/18 |  John     |  Pass   |       1        |
|  03 |  03/08/18 |  John     |  Fail   |       2        |
|  04 |  01/08/18 |  Mark     |  Fail   |       1        |
|  05 |  02/08/18 |  Mark     |  Pass   |       0        |

我真的很想让它起作用,最后我求助于使用VBA为每个唯一的人创建一个记录集,然后每天遍历该人以检查他们那天是否失败。我的数据集很大,需要几个小时才能运行。

我希望对整个数据集进行操作的查询会更快。有人知道这是否有SQL解决方案吗?

1 个答案:

答案 0 :(得分:2)

您需要几个子查询来获得通过测试且没有失败的最后日期,然后计算该日期与testDate之间的天数:

SELECT t1.ID
    ,t1.testDate
    ,t1.Person
    ,t1.[Pass?]
    ,(
        SELECT count(testDate)
        FROM (
            SELECT DISTINCT testDate
                ,Person
                ,[Pass?]
            FROM yourTable
            ) AS t2
        WHERE t2.[Pass?] = false
            AND t2.Person = t1.Person
            AND t2.testDate >= Nz((
                            SELECT max(t3.testDate)
                            FROM (
                                SELECT t4.testDate
                                    ,t4.Person
                                FROM yourTable AS t4
                                WHERE (
                                        ((t4.[Pass?]) = True)
                                        AND (
                                            (
                                                (
                                                    SELECT count(*) AS failed
                                                    FROM yourTable AS t5
                                                    WHERE t5.testDate = t4.testDate
                                                        AND t5.Person = t4.Person
                                                        AND t5.[Pass?] = false
                                                    )
                                                ) = 0
                                            )
                                        )
                                ) AS t3
                            WHERE t1.Person = t3.Person
                                AND t3.testDate <= [t1].[testDate]
                            GROUP BY Person
                            ))
                AND t2.testDate <= t1.testDate
        ) AS ConsecFailDays
FROM yourTable AS t1;

t2计算不同的天数(如果每天只有一次失败可以加快速度,则可以放弃DISTINCT

t3是通过测试且没有失败的日子。

t4是通过测试(或可能失败的测试)的日子。

t5每天将通过测试的失败测试计算在内。

您需要Update-Query时可以使用:

UPDATE yourTable SET ConsecFailDays = DLookUp("ConsecFailDays","newQuery","ID = " & yourTable.ID)

,但是您应该首先尝试将Select-Query与索引一起使用。如果性能太差,则可以使用此更新,但是每次数据更改时都必须运行该更新。

建议:

  • 请勿在列名或表名中使用?中的Pass?之类的特殊字符,以免被迫使用方括号。

  • 人应该是餐桌人的外键,因为人的名字可以相同(例如John Smith)。

  • [Pass?]应该为布尔值(是/否)。如果要保留字符串,则必须将[Pass?] = false替换为[Pass?] = 'Fail',将[Pass?] = true替换为 [Pass?] = 'Pass'
  • 应该有testDatePerson的索引和testDate, Person的组合索引,以提高查询性能。