我正在尝试创建简单的需求管理数据库。基本上我有2张桌子,如下所示:
具有2列的Contract_requirements:
CR_ReqID | Description
reqCR1 | Contract req description 1
reqCR2 | Contract req description 2
SW_requirements
Title | SW_ReqID | RootReq
SW req description 1| reqSW1 | reqCR1, reqCR2
SW req description 2| reqSW2 | reqCR1
SW req description 3| reqSW3 | reqCR2
我想编写查询以接收这样的表:
CR_ReqID |Description |where used?
reqCR1 |Contract req description 1 |reqSW1, reqSW2
reqCR2 |Contract req description 2 |reqSW1, reqSW3
通过“ RootReq”列关联“合同要求”和“软件要求”表
我曾经尝试实现Allen Browne的代码 http://allenbrowne.com/func-concat.html#Top
这是我的查询
SELECT Contract_requirements.CR_ReqID, ConcatRelated("SW_ReqID ","SW_requirements","RootReq = """ & [CR_ReqID] & """") AS Expr1
FROM Contract_requirements;
但是访问时出现错误
“错误3831:不能在WHERE或HAVING子句中使用多值字段'RootReq'”
你们能帮助我使它正常工作吗? 预先感谢
答案 0 :(得分:1)
构建一个查询,将多值字段元素扩展为单个记录。
Query1
SELECT SW_Requirements.Title, SW_Requirements.SW_ReqID, SW_Requirements.RootReq.Value
FROM SW_Requirements;
然后将该查询用作ConcatRelated()函数的源。
SELECT Contract_Requirements.*,
ConcatRelated("SW_ReqID","Query1","[SW_Requirements.RootReq.Value]='" & [CR_ReqID] & "'") AS WhereUsed
FROM Contract_Requirements;
建议在命名约定中不要使用空格或标点/特殊字符。
答案 1 :(得分:1)
您还可以使用我的 DJoin 函数,因为它将接受SQL作为源,因此您不需要其他已保存的查询:
' Returns the joined (concatenated) values from a field of records having the same key.
' The joined values are stored in a collection which speeds up browsing a query or form
' as all joined values will be retrieved once only from the table or query.
' Null values and zero-length strings are ignored.
'
' If no values are found, Null is returned.
'
' The default separator of the joined values is a space.
' Optionally, any other separator can be specified.
'
' Syntax is held close to that of the native domain functions, DLookup, DCount, etc.
'
' Typical usage in a select query using a table (or query) as source:
'
' Select
' KeyField,
' DJoin("[ValueField]", "[Table]", "[KeyField] = " & [KeyField] & "") As Values
' From
' Table
' Group By
' KeyField
'
' The source can also be an SQL Select string:
'
' Select
' KeyField,
' DJoin("[ValueField]", "Select ValueField From SomeTable Order By SomeField", "[KeyField] = " & [KeyField] & "") As Values
' From
' Table
' Group By
' KeyField
'
' To clear the collection (cache), call DJoin with no arguments:
'
' DJoin
'
' Requires:
' CollectValues
'
' 2019-06-24, Cactus Data ApS, Gustav Brock
'
Public Function DJoin( _
Optional ByVal Expression As String, _
Optional ByVal Domain As String, _
Optional ByVal Criteria As String, _
Optional ByVal Delimiter As String = " ") _
As Variant
' Expected error codes to accept.
Const CannotAddKey As Long = 457
Const CannotReadKey As Long = 5
' SQL.
Const SqlMask As String = "Select {0} From {1} {2}"
Const SqlLead As String = "Select "
Const SubMask As String = "({0}) As T"
Const FilterMask As String = "Where {0}"
Static Values As New Collection
Dim Records As DAO.Recordset
Dim Sql As String
Dim SqlSub As String
Dim Filter As String
Dim Result As Variant
On Error GoTo Err_DJoin
If Expression = "" Then
' Erase the collection of keys.
Set Values = Nothing
Result = Null
Else
' Get the values.
' This will fail if the current criteria hasn't been added
' leaving Result empty.
Result = Values.Item(Criteria)
'
If IsEmpty(Result) Then
' The current criteria hasn't been added to the collection.
' Build SQL to lookup values.
If InStr(1, LTrim(Domain), SqlLead, vbTextCompare) = 1 Then
' Domain is an SQL expression.
SqlSub = Replace(SubMask, "{0}", Domain)
Else
' Domain is a table or query name.
SqlSub = Domain
End If
If Trim(Criteria) <> "" Then
' Build Where clause.
Filter = Replace(FilterMask, "{0}", Criteria)
End If
' Build final SQL.
Sql = Replace(Replace(Replace(SqlMask, "{0}", Expression), "{1}", SqlSub), "{2}", Filter)
' Look up the values to join.
Set Records = CurrentDb.OpenRecordset(Sql, dbOpenSnapshot)
CollectValues Records, Delimiter, Result
' Add the key and its joined values to the collection.
Values.Add Result, Criteria
End If
End If
' Return the joined values (or Null if none was found).
DJoin = Result
Exit_DJoin:
Exit Function
Err_DJoin:
Select Case Err
Case CannotAddKey
' Key is present, thus cannot be added again.
Resume Next
Case CannotReadKey
' Key is not present, thus cannot be read.
Resume Next
Case Else
' Some other error. Ignore.
Resume Exit_DJoin
End Select
End Function
' To be called from DJoin.
'
' Joins the content of the first field of a recordset to one string
' with a space as delimiter or an optional delimiter, returned by
' reference in parameter Result.
'
' 2019-06-11, Cactus Data ApS, Gustav Brock
'
Private Sub CollectValues( _
ByRef Records As DAO.Recordset, _
ByVal Delimiter As String, _
ByRef Result As Variant)
Dim SubRecords As DAO.Recordset
Dim Value As Variant
If Records.RecordCount > 0 Then
While Not Records.EOF
Value = Records.Fields(0).Value
If Records.Fields(0).IsComplex Then
' Multi-value field (or attachment field).
Set SubRecords = Records.Fields(0).Value
CollectValues SubRecords, Delimiter, Result
ElseIf Nz(Value) = "" Then
' Ignore Null values and zero-length strings.
ElseIf IsEmpty(Result) Then
' First value found.
Result = Value
Else
' Join subsequent values.
Result = Result & Delimiter & Value
End If
Records.MoveNext
Wend
Else
' No records found with the current criteria.
Result = Null
End If
Records.Close
End Sub
完整的文档可以在我的文章中找到:
Join (concat) values from one field from a table or query
如果您没有帐户,请浏览链接:阅读全文。
代码也在 GitHub 上:VBA.DJoin