【问题标题】:SQL - How to discard groups of results based on date range (microsoft access)SQL - 如何根据日期范围丢弃结果组(微软访问)
【发布时间】:2016-02-10 14:27:28
【问题描述】:

我有一个包含许多患者病理结果的 Access 数据库,其中通常包括在一段时间内为同一患者收集的许多样本。我想保留每位患者的第一个记录,但丢弃同一患者在 14 天内发生的所有后续记录。但如果 14 天后还有更多样本,请保留第一个后续样本,然后再次丢弃接下来 14 天的样本。

该表有很多列,但最重要的是patient IDsample collection date

我需要了解如何编写 SQL 语句来选择这些初始记录,但在随后的 14 天内丢弃这些记录。我认为它可能与between 命令有关,但我不确定如何使开始日期和结束日期可变以及如何使其在整个数据集上递归。

【问题讨论】:

  • 我认为您无法在一个查询中完成。您将需要遍历每个患者 ID,找到他们的第一个日期,在 14 天内删除任何内容,找到下一个日期并重复。当您说丢弃时,您的意思是从表中删除还是仅从结果中删除?如果是后者,那么您需要将患者 ID 和日期添加到一个临时表中,而不是删除,以链接回最终输出

标签: sql date ms-access recursion duplicates


【解决方案1】:

你试过 Max() 函数吗?您可以使用它为每个患者 ID 选择最新的 SampleDate

类似这样的:

Select PatentID, Max(SampleDate)
From SpecimenTable
Where CollectionDate between Date1 and Date2
Group By PatientID

您需要在 group by 语句中包含除 Max(SampleDate) 以外的 select 语句中的每个字段。

【讨论】:

    【解决方案2】:

    纯粹是“aircode”,我没有太多时间来做这个,但如果它没有意义,那么也许其他人可以使用它来提出一个完整的解决方案:

    'Keep the first record in the first 14 days
    Select PatentID, Max(SampleDate)
    From SpecimenTable
    Where CollectionDate between Now() and DateAdd("d", Now(), -14)
    Group By PatientID
    
    UNION ALL
    
    'Keep the first record of everything after the first 14 days
    Select PatentID, Max(SampleDate)
    From SpecimenTable
    Where CollectionDate < DateAdd("d", Now(), -15)
    Group By PatientID
    

    显然您不能在查询中使用 cmets,因此您需要删除这些。我只是把它们放进去展示我的思考过程。

    【讨论】:

      【解决方案3】:

      不确定如何纯粹在 SQL 中执行此操作,但这里有一些(带注释的)VBA 代码,我认为它们可以满足您的要求:

      Dim db As DAO.Database
      Dim strSql As String
      Dim rsPat As DAO.Recordset
      
      Set db = CurrentDb
      
      ' Get ourselves an ordered list of unique patients to work through
      
      strSql = "SELECT PatientID " _
             & " FROM tblPatientSamplesExample" _
             & " GROUP BY PatientID" _
             & " ORDER BY PatientID"
      
      Set rsPat = db.OpenRecordset(strSql)
      
      With rsPat
      
          If _
              Not (.BOF And .EOF) _
          Then
      
              .MoveFirst
      
              Do While Not .EOF
      
                  ' For the patient we're working on, make another list that shows the records
                  ' in our table for this particular patient, ordered by the sample collection date
      
                  Dim rsPatSampRecs As DAO.Recordset
                  Dim refDate As Variant
                  Dim currDate As Variant
      
                  strSql = "SELECT * " _
                         & " FROM tblPatientSamplesExample" _
                         & " WHERE PatientID=" & rsPat!PatientID _
                         & " ORDER BY SampleCollectionDate ASC"
      
                  Set rsPatSampRecs = db.OpenRecordset(strSql)
      
                  With rsPatSampRecs
      
                      If _
                          Not (.BOF And .EOF) _
                      Then
      
                          .MoveFirst
                          ' Set the earliest sample collection date for this patient as the reference date to use
                          refDate = CDbl(rsPatSampRecs!SampleCollectionDate)
      
                          Do While Not .EOF
      
                              ' Set the current record's sample collection date for this patient as the current date to compare
                              currDate = CDbl(rsPatSampRecs!SampleCollectionDate)
      
                              ' if currDate is 14 or more greater than refDate then update the refDate to the currDate
                              If _
                                  currDate >= (refDate + 14) _
                              Then
      
                                  refDate = currDate
      
                              End If
      
                              ' if currDate is not the same as the refDate delete the record from
                              ' tblPatientSamplesExample by matching PatientSampleID of this temp recordset
                              ' to the one in the actual table
      
                              If _
                                  currDate <> refDate _
                              Then
      
                                  strSql = "DELETE * FROM tblPatientSamplesExample" _
                                         & " WHERE PatientSampleID=" & rsPatSampRecs!PatientSampleID
      
                                  CurrentDb.Execute strSql
      
                              End If
      
                              .MoveNext
      
                          Loop
      
                      End If
      
                  End With
      
                  rsPatSampRecs.Close
                  Set rsPatSampRecs = Nothing
                  .MoveNext
      
              Loop
      
          End If
      
      End With
      
      
      rsPat.Close
      
      Set rsPat = Nothing
      Set db = Nothing
      

      Here's 我的模型访问文件也是。我将“丢弃记录”解释为“删除记录”,因此在执行此操作之前要小心(备份您的数据)。

      【讨论】:

      • 刚刚意识到我错过了CurrentDb.Execute strSql 这行,这对于删除您不想要的记录非常重要!答案已更新。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多