用于输入具有多个字段的查询条件的参数表单,其中包含一个值或一个空值

Parameter Form to Input Query Criteria with Multiple Fields Either With a Value or Null

我构建了一个带有未绑定字段的表单,用户可以输入日期范围、设施名称(这些来自组合框)和徽章编号以在 Access 中生成查询。如果该字段留空,我希望能够在选定的日期范围内为所有设施获得 return 结果,或者如果选择了某个设施,则只为特定设施的结果。我还希望能够将结果限制为与某人的徽章编号相匹配的结果。

所以我想要的可能性是:

  1. 日期范围=由用户定义|设施 - 如果未选择则全部 |徽章# = All if not selected
  2. 日期范围=由用户定义|设施 - 如果未选择则全部 |徽章 # = 由用户定义
  3. 日期范围=由用户定义|设施 - 由用户定义 |徽章# = All if not selected
  4. 日期范围=由用户定义|设施 - 由用户定义 |徽章 # = 由用户定义

我最初只用日期范围和设施名称构建它,它运行良好。当我尝试添加 Badge # 时,它并没有真正正常工作。

我的 WHERE TO 部分的 SQL 是:

WHERE (((Diversion.Transaction_Date) Between [Forms]![Parameters]![FromDate] And [Forms]![Parameters]![ToDate]) 
AND ((Diversion.Employee_Badge_Number)=[Forms]![Parameters]![BadgeNumber]) 
AND ((Diversion.Facility)=[Forms]![Parameters]![FacilitySelect])) 
OR (((Diversion.Transaction_Date) Between [Forms]![Parameters]![FromDate] And [Forms]![Parameters]![ToDate]) 
AND ((Diversion.Facility)=[Forms]![Parameters]![FacilitySelect]) 
AND ((([Diversion].[Employee_Badge_Number]) Like [Forms]![Parameters]![BadgeNumber]) Is Null)) 
OR (((Diversion.Transaction_Date) Between [Forms]![Parameters]![FromDate] And [Forms]![Parameters]![ToDate]) 
AND ((Diversion.Employee_Badge_Number)=[Forms]![Parameters]![BadgeNumber]) 
AND ((([Diversion].[Facility]) Like [Forms]![Parameters]![FacilitySelect]) Is Null)) 
OR (((Diversion.Transaction_Date) Between [Forms]![Parameters]![FromDate] And [Forms]![Parameters]![ToDate]) 
AND ((([Diversion].[Employee_Badge_Number]) Like [Forms]![Parameters]![BadgeNumber]) Is Null) 
AND ((([Diversion].[Facility]) Like [Forms]![Parameters]![FacilitySelect]) Is Null)) 
OR (((([Diversion].[Facility]) Like [Forms]![Parameters]![FacilitySelect]) Is Null));

对我来说,它似乎包含了我想从表单中获得的四种可能结果,但它无法正常工作。例如,如果我将设施字段留空,并定义徽章编号,它仍然会为我提供所有结果。如果我定义设施并定义徽章编号,它确实会给我正确的结果。

有什么想法吗?

这可能会给您一些构建具有多个条件值的动态查询的想法。在此示例中,用户可以选择任意数量的条件。它写在VB.Net中。它适用于 Access。我检查每个字段以查看是否提供了任何条件,如果存在有效值,则将其附加到查询中。 我使用 Interpolated strings 只是因为它更容易看到空格的位置。备选方案是:

String.Format("RoasterId = {0} ", itgRoaster)

我还使用了字符串生成器,这是一种更改字符串的有效方法,无需在每次追加时创建和处理它们的开销。如果在 VBA.

中不可用,您可以只使用 &=
Dim bolNeedAnd As Boolean = False
        Dim sb As New Text.StringBuilder
        sb.Append("SELECT Coffees.ID, Coffees.[Name], Coffees.RoasterID, Roasters.[Name], Coffees.[Type],Coffees.Rating, Coffees.Comment, Coffees.Description, Coffees.Roast, Coffees.IsExtraBold, Coffees.IsFavorite
    From Coffees Inner Join Roasters on Coffees.RoasterID = Roasters.ID Where ")
        If itgRoaster <> 0 Then
            sb.Append($"RoasterID = {itgRoaster} ")
            bolNeedAnd = True
        End If
        If strRoast <> "" Then
            If bolNeedAnd Then
                sb.Append($"AND Roast = '{strRoast}' ")
            Else
                sb.Append($"Roast = '{strRoast}' ")
            End If
            bolNeedAnd = True
        End If
        If strType <> "" Then
            If bolNeedAnd Then
                sb.Append($"AND Type = '{strType}' ")
            Else
                sb.Append($"Type = '{strType}' ")
            End If
            bolNeedAnd = True
        End If
        If strRating <> "" Then
            If bolNeedAnd Then
                sb.Append($"AND Rating = '{strRating}' ")
            Else
                sb.Append($"Rating = '{strRating}' ")
            End If
            bolNeedAnd = True
        End If
        If bolBold Then
            If bolNeedAnd Then
                sb.Append("AND IsExtraBold = 1 ")
            Else
                sb.Append("IsExtraBold = 1 ")
            End If
            bolNeedAnd = True
        End If
        If bolFavorite Then
            If bolNeedAnd Then
                sb.Append("AND IsFavorite = 1 ")
            Else
                sb.Append("IsFavorite = 1 ")
            End If
        End If
        sb.Append("Order By Coffees.[Name];")
        Debug.Print(sb.ToString)

        Dim cmd As New OleDbCommand With {
            .Connection = cn,
            .CommandType = CommandType.Text,
            .CommandText = sb.ToString}