我在MSAccess中收到了查询结果。
QueryMatch :
InvoiceNumber RegionNumber Group
9448180 73657 A
9448180 74170 A
9448180 74171 A
9448180 78761 A
9448196 73657 A
9448196 74170 A
9448196 74171 A
9448196 78761 A
9448201 73657 A
9448201 74170 A
9448201 74171 A
9448201 78761 A
1234567 12345 B
so on..
Table 2:
RegionNumber InvoiceNumber
73657
74170
74171
78761
查询有一个长列表,由组分隔。 对于x InvoiceNumbers,可以有x + n RegionNumber。 n = 0到25。 一个RegionNumber必须仅与每个组的一个InvoiceNumber匹配。 我们如何更新Table2?
让我们为最小的RegionNumber做匹配,以匹配Matchresult中最小的InvoiceNumber。
将最后一个RegionNumber保留为NULL。
请提供VBA或仅通过查询完成此操作? 为每个RegionNumber选择MIN(InvoiceNumber)将产生相同的InvoiceNumber。
由于
答案 0 :(得分:1)
让我们考虑以下[QueryMatch]示例数据
InvoiceNumber RegionNumber Group
123 678 A
234 678 A
345 678 A
123 789 A
我们可以尝试迭代RegionNumber值(升序)并选择最低的InvoiceNumber,但这种方法最终会失败。我们将InvoiceNumber 123分配给RegionNumber 678,然后当处理RegionNumber 789时,唯一可能的选择是InvoiceNumber 123并且它已被采用。
因此,我们最好先获取RegionNumber值的列表以及每个值具有的不同InvoiceNumbers的数量。这将让我们首先处理最受约束的RegionNumber值。
SELECT qm.RegionNumber, Count(qm.InvoiceNumber) AS NumDistinctInvoiceNumbers
FROM
(
SELECT DISTINCT RegionNumber, InvoiceNumber FROM QueryMatch
) qm
GROUP BY qm.RegionNumber
ORDER BY 2 ASC
...返回......
RegionNumber NumDistinctInvoiceNumbers
789 1
678 3
...让我们知道我们需要首先处理RegionNumber 789,然后将其中一个“剩余”分配给RegionNumber 678.
现在,要找到给定RegionNumber的最低未使用的 InvoiceNumber,我们需要排除已经写入[Table 2]的任何一个。因此,假设我们已经将InvoiceNumber 123“赋予”RegionNumber 789,那么找到RegionNumber 678的合适候选者的一种方法是...
DMin("InvoiceNumber", "QueryMatch", "RegionNumber=678 AND InvoiceNumber NOT IN (Select InvoiceNumber FROM [Table 2])")
...将返回最小的未使用的InvoiceNumber,如果找不到,则返回Null
。
在一些VBA代码中包含它,我们得到
Public Sub AssignInvoicesToRegions()
Dim cdb As DAO.Database, rstRegion As DAO.Recordset, rst2 As DAO.Recordset
Dim vInvNo As Variant
Set cdb = CurrentDb
Set rst2 = cdb.OpenRecordset("Table 2", dbOpenDynaset)
Set rstRegion = cdb.OpenRecordset( _
"SELECT qm.RegionNumber, Count(qm.InvoiceNumber) AS NumDistinctInvoiceNumbers " & _
"FROM " & _
"( " & _
"SELECT DISTINCT RegionNumber, InvoiceNumber FROM QueryMatch " & _
") qm " & _
"GROUP BY qm.RegionNumber " & _
"ORDER BY 2 ASC", _
dbOpenSnapshot)
Do While Not rstRegion.EOF
Debug.Print rstRegion!RegionNumber
vInvNo = DMin("InvoiceNumber", "QueryMatch", "RegionNumber=" & rstRegion!RegionNumber & " " & _
"AND InvoiceNumber NOT IN (Select Nz(InvoiceNumber, 0) AS InvNo FROM [Table 2])")
If IsNull(vInvNo) Then
MsgBox "No available InvoiceNumber for RegionNumber=" & rstRegion!RegionNumber, _
vbCritical, "Lookup Failed"
Else
rst2.FindFirst "RegionNumber=" & rstRegion!RegionNumber
rst2.Edit
rst2!InvoiceNumber = vInvNo
rst2.Update
End If
rstRegion.MoveNext
Loop
Debug.Print "Done."
rstRegion.Close
Set rstRegion = Nothing
rst2.Close
Set rst2 = Nothing
Set cdb = Nothing
End Sub
请注意,在当前形式下,此算法不是保证为每个RegionNumber找到匹配项。根据处理RegionNumber值的顺序,某些区域可能会发现所有候选项都已被采用(因此代码中的IsNull()
检查)。在这种情况下,您可能需要调整算法,以便在InvoiceNumber中为这些区域“第一次拍摄”,可能通过手动为这些“困难”区域分配更高的优先级。