查找分组值,然后连接行

时间:2015-08-13 19:12:42

标签: sql algorithm vba ms-access

我在编写一个或多个查询时遇到问题,这些查询会获得我想要的结果。

基本上,我正在努力寻找独特的公司。"问题是一些公司拥有在同一地址运营的多个业务。我希望连接这些值,而不是重复在2个地址运行的1家公司的结果。

示例数据:

Company  Address
A        1
A        2
B        1
C        3

所以我们有唯一的companies

A
B
C

addresses

1
2
3

我想获得两条结果记录:

A, B
C

(理想情况下,在第一个表格中,A-1,A-2和B-1的结果都指向不同字段中的相同自动编号。)

1 个答案:

答案 0 :(得分:1)

澄清:

  • 企业可以拥有多个地址
  • 业务组中的任何业务(AKA公司)与该组中的任何其他业务共享地址
  • 业务组可以拥有多个业务
  • 每项业务仅与一个业务组相关联(推论第二点)

SqlFiddle with sample data

我们可以通过组中的第一个(按字母顺序排列的最小名称)业务来引用每个业务组。我们称之为关键业务。在我们确定了每项业务的关键业务后,我们可以按关键业务进行分组并获得结果。

为了获得关键业务:

  • 根据任何共享地址生成两个业务位于同一组中的业务对列表。此列表应排除以下内容(请参阅下一个原因):

    1. A -> B,当我们有B -> A
    2. A -> A
    3. 对的左侧应该是唯一的:如果有的话,每个业务应该出现在对的左侧不超过一次。

    4. 对于每个企业,请遵循从一对到另一个企业的配对,直到正确的企业永远不是任何其他企业的左企业。这是关键业务。

      这就是第一点排除的原因。如果我们同时拥有A -> BB -> A,我们将会进入一个永无止境的循环。同样适用于A -> A

第一部分可以在纯SQL中直接完成:

SELECT Businesses.Business AS Business2, MIN(Businesses_1.Business) AS Business1
FROM Businesses
INNER JOIN Businesses AS Businesses_1 ON Businesses.Address = Businesses_1.Address
WHERE Businesses.Business > Businesses_1.Business
GROUP BY Businesses.Business

SqlFiddle

(其他RDBMS支持recursive joining,因此对于第二部分,我们可以从源数据开始,并指示数据库无限期地继续加入,直到最终Business1NULL。{{ 3}}。AFAIK MS Access在SQL中不支持此功能,因此我们必须在VBA中执行此操作。)

我建议将Scripting.Dictionary用于此目的。您需要添加对 Microsoft Scripting Runtime 的引用(工具 - >引用... )。

'Create a Dictionary to hold the pairs
Dim pairs As New Scripting.Dictionary

'Load the pairs using the above SQL
Dim sql = _
    "SELECT Businesses.Business AS Business2, MIN(Businesses_1.Business) AS Business1 " & _
    "FROM Businesses " & _
    "INNER JOIN Businesses AS Businesses_1 ON Businesses.Address = Businesses_1.Address " & _
    "WHERE Businesses.Business > Businesses_1.Business " & _
    "GROUP BY Businesses.Business"
Dim rsPairs = CurrentDb.OpenRecordset(sql, dbOpenForwardOnly)
Do Until rsPairs.EOF
    pairs(rsPairs!Business2) = rsPairs!Business1
Loop
rsPairs.Close
Set rsPairs = Nothing

'Create a Dictionary to hold the groupings
Dim groupings As New Scripting.Dictionary

sql = _
    "SELECT DISTINCT Business " & _
    "FROM Businesses " & _
    "ORDER BY Business"        
Dim rsBusinesses As DAO.Recordset
Set rsBusinesses = CurrentDb.OpenRecordSet(sql, dbOpenForwardOnly)
Do Until rsBusinesses.EOF
    Dim business As String
    business = rsBusinesses!Business
    If Not pairs.Exists(business) Then
        Dim col As New Collection
        col.Add(business)
        groupings(business) = col
    Else
        'Find the group's key business
        Dim prevBusiness As String
        prevBusiness = business
        Do While pairs.Exists(prevBusiness)
            prevBusiness = pairs(prevBusiness)
        Loop
        groupings(prevBusiness).Add(business)
    End If
Loop

最终的词典将如下所示:

Key    Collection
A      (A, B, W, X)
C      (C)
D      (D, E, F, G)

可以按如下方式迭代:

Dim key As Variant, item As Variant
For Each key In groupings
    Debug.Print "Grouping " & key
    For Each item In groupings(key)
        Debug.Print "Business - " & item
    Next
Next