Sql 表示实体网络之间关系的流程数据

Sql 表示实体网络之间关系的流程数据,sql,Sql,事实如下: 有很多公司 每个公司都可以有很多业务 有很多地址 你不知道哪些公司(或公司名称)拥有哪些业务 但是,您知道每家企业的地址,并且您知道一家企业可能在多个地址进行交易 在地址之间建立关系: 如果一家企业的地址与另一家企业的地址相同,那么就这个问题而言,我们会说它们属于同一家公司 当一家公司同时使用两个地址时,两个地址之间就形成了链接 因此,一个地址“A”可能链接到许多其他地址 请注意: 6a。地址“A”链接到的地址也可能链接到一个或多个地址 6b。“A”链接到的其中一个地址可能通过第三个

事实如下:

  • 有很多公司

  • 每个公司都可以有很多业务

  • 有很多地址

  • 你不知道哪些公司(或公司名称)拥有哪些业务

  • 但是,您知道每家企业的地址,并且您知道一家企业可能在多个地址进行交易

  • 在地址之间建立关系:

  • 如果一家企业的地址与另一家企业的地址相同,那么就这个问题而言,我们会说它们属于同一家公司
  • 当一家公司同时使用两个地址时,两个地址之间就形成了链接

    因此,一个地址“A”可能链接到许多其他地址

    请注意:

    6a。地址“A”链接到的地址也可能链接到一个或多个地址

    6b。“A”链接到的其中一个地址可能通过第三个地址链接回“A”(即使用这两个地址的两个企业)

    一个复杂的例子如所附图片所示。在这张图片中,只有两家公司。一家是红色业务,另一家是蓝色、绿色和黑色业务

    以下是tableBA中的一些示例数据(我附上了一张照片来描述这些关系)

    这个问题是对另一个SO问题的简化/改进

    对于另一个问题,使用SQL和VBA代码的组合来解决问题,因为MS Access不支持


    如何使用纯SQL实现这一点,无论是使用递归连接还是其他技术(不是使用存储过程)?

    这是一个粗糙而蹩脚的解决方案(可能效率不高),但它得到了正确的结果。它通过维护到公司的两个映射(其中公司包含一个企业名称列表)来实现。第一个将业务地址映射到公司,第二个将业务名称映射到公司。如果在任一映射中都找不到公司,则会创建一个新公司:-

    package test;
    
    import org.junit.Assert;
    import org.junit.Test;
    
    import java.util.*;
    import java.util.stream.Collectors;
    
    public class Companies {
        public static List<Company> listCompanies(List<Business> businesses) {
            List<Company> companies = new ArrayList<>();
            Map<String, Company> companyByAddress = new HashMap<>(); // map allows many addresses to map to same company
            Map<String, Company> companyByBusiness = new HashMap<>(); // map allows many businesses to map to same company
    
            for (Business business : businesses) {
                Company company = companyByAddress.get(business.address);
                if (company == null)
                    company = companyByBusiness.get(business.name);
    
                if (company != null) {
                    company.addAddress(business.name);
                } else {
                    company = new Company();
                    company.addAddress(business.name);
                    companies.add(company);
                }
    
                companyByBusiness.put(business.name, company);
                companyByAddress.put(business.address, company);
            }
    
            return companies;
        }
    
        @Test
        public void testOne() {
            List<Business> businesses = new ArrayList<>();
            businesses.add(new Business("A", "1"));
            businesses.add(new Business("A", "2"));
            businesses.add(new Business("B", "1"));
            businesses.add(new Business("C", "3"));
            businesses.add(new Business("D", "4"));
            businesses.add(new Business("E", "4"));
            businesses.add(new Business("F", "4"));
            businesses.add(new Business("G", "4"));
            businesses.add(new Business("W", "2"));
            businesses.add(new Business("W", "5"));
            businesses.add(new Business("X", "5"));
            businesses.add(new Business("X", "6"));
    
            List<Company> companies = listCompanies(businesses);
    
            Assert.assertEquals("A, B, W, X", companies.get(0));
            Assert.assertEquals("C", companies.get(1));
            Assert.assertEquals("D, E, F, G", companies.get(2));
        }
    
        static class Business {
            private final String name;
            private final String address;
    
            Business(String business, String address) {
                this.name = business;
                this.address = address;
            }
        }
    
        static class Company {
            private final Set<String> addresses; // Being a "Set", each address will occur only once
    
            Company() {
                this.addresses = new LinkedHashSet<>(); // A "LinkedHashSet" preserves insertion order
            }
    
            void addAddress(String address) {
                addresses.add(address);
            }
    
            @Override
            public String toString() {
                return addresses.stream().collect(Collectors.joining(", "));
            }
        }
    }
    
    封装测试;
    导入org.junit.Assert;
    导入org.junit.Test;
    导入java.util.*;
    导入java.util.stream.collector;
    上市公司{
    公开静态上市公司(上市业务){
    上市公司=新ArrayList();
    Map companyByAddress=new HashMap();//Map允许多个地址映射到同一个公司
    Map companybusiness=new HashMap();//Map允许多个业务映射到同一个公司
    用于(业务:业务){
    Company Company=companyByAddress.get(business.address);
    如果(公司==null)
    company=companybusiness.get(business.name);
    如果(公司!=null){
    公司地址(业务名称);
    }否则{
    公司=新公司();
    公司地址(业务名称);
    公司。添加(公司);
    }
    companybusiness.put(business.name,company);
    companyByAddress.put(business.address,company);
    }
    返回公司;
    }
    @试验
    公共void testOne(){
    列表业务=新建ArrayList();
    增加(新业务(“A”、“1”));
    增加(新业务(“A”、“2”));
    增加(新业务(“B”、“1”);
    增加(新业务(“C”、“3”));
    增加(新业务(“D”、“4”);
    增加(新业务(“E”、“4”));
    增加(新业务(“F”、“4”));
    增加(新业务(“G”、“4”));
    增加(新业务(“W”、“2”));
    增加(新业务(“W”、“5”));
    增加(新业务(“X”、“5”));
    增加(新业务(“X”、“6”));
    上市公司=上市公司(企业);
    Assert.assertEquals(“A,B,W,X”,companys.get(0));
    Assert.assertEquals(“C”,companys.get(1));
    Assert.assertEquals(“D,E,F,G”,companys.get(2));
    }
    静态类业务{
    私有最终字符串名;
    私有最终字符串地址;
    业务(字符串业务,字符串地址){
    this.name=业务;
    this.address=地址;
    }
    }
    静态类公司{
    私有最终集地址;//作为一个“集”,每个地址只出现一次
    公司(){
    this.addresses=new LinkedHashSet();//一个“LinkedHashSet”保留插入顺序
    }
    无效地址(字符串地址){
    地址。添加(地址);
    }
    @凌驾
    公共字符串toString(){
    返回地址.stream().collect(collector.joining(“,”);
    }
    }
    }
    
    这是SQL Server的答案

    引述答覆:

    澄清:

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

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

    为了获得关键业务:

    WITH Pairs AS (
      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
    ),
    KeyBusinesses AS (
      SELECT Business2 AS Business, Business1 AS KeyBusiness
      FROM Pairs
      UNION ALL 
      SELECT Pairs.Business2, KeyBusinesses.KeyBusiness
      FROM Pairs
      INNER JOIN KeyBusinesses ON Pairs.Business1 = KeyBusinesses.Business
    )
    
    SELECT Businesses.*, ISNULL(KeyBusinesses.KeyBusiness, Businesses.Business) AS KeyBusiness
    FROM Businesses
    LEFT JOIN KeyBusinesses ON Businesses.Business = KeyBusinesses.Business
    
    • 根据任何共享地址生成两个业务位于同一组中的业务对列表。此列表应排除 以下内容(原因见下一点):

    • A->B
      ,当我们有
      B->A
    • A->A
    • 对的左侧应该是唯一的:每个业务应该出现在对的左侧不超过一次,如果有的话<
      package test;
      
      import org.junit.Assert;
      import org.junit.Test;
      
      import java.util.*;
      import java.util.stream.Collectors;
      
      public class Companies {
          public static List<Company> listCompanies(List<Business> businesses) {
              List<Company> companies = new ArrayList<>();
              Map<String, Company> companyByAddress = new HashMap<>(); // map allows many addresses to map to same company
              Map<String, Company> companyByBusiness = new HashMap<>(); // map allows many businesses to map to same company
      
              for (Business business : businesses) {
                  Company company = companyByAddress.get(business.address);
                  if (company == null)
                      company = companyByBusiness.get(business.name);
      
                  if (company != null) {
                      company.addAddress(business.name);
                  } else {
                      company = new Company();
                      company.addAddress(business.name);
                      companies.add(company);
                  }
      
                  companyByBusiness.put(business.name, company);
                  companyByAddress.put(business.address, company);
              }
      
              return companies;
          }
      
          @Test
          public void testOne() {
              List<Business> businesses = new ArrayList<>();
              businesses.add(new Business("A", "1"));
              businesses.add(new Business("A", "2"));
              businesses.add(new Business("B", "1"));
              businesses.add(new Business("C", "3"));
              businesses.add(new Business("D", "4"));
              businesses.add(new Business("E", "4"));
              businesses.add(new Business("F", "4"));
              businesses.add(new Business("G", "4"));
              businesses.add(new Business("W", "2"));
              businesses.add(new Business("W", "5"));
              businesses.add(new Business("X", "5"));
              businesses.add(new Business("X", "6"));
      
              List<Company> companies = listCompanies(businesses);
      
              Assert.assertEquals("A, B, W, X", companies.get(0));
              Assert.assertEquals("C", companies.get(1));
              Assert.assertEquals("D, E, F, G", companies.get(2));
          }
      
          static class Business {
              private final String name;
              private final String address;
      
              Business(String business, String address) {
                  this.name = business;
                  this.address = address;
              }
          }
      
          static class Company {
              private final Set<String> addresses; // Being a "Set", each address will occur only once
      
              Company() {
                  this.addresses = new LinkedHashSet<>(); // A "LinkedHashSet" preserves insertion order
              }
      
              void addAddress(String address) {
                  addresses.add(address);
              }
      
              @Override
              public String toString() {
                  return addresses.stream().collect(Collectors.joining(", "));
              }
          }
      }
      
      WITH Pairs AS (
        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
      ),
      KeyBusinesses AS (
        SELECT Business2 AS Business, Business1 AS KeyBusiness
        FROM Pairs
        UNION ALL 
        SELECT Pairs.Business2, KeyBusinesses.KeyBusiness
        FROM Pairs
        INNER JOIN KeyBusinesses ON Pairs.Business1 = KeyBusinesses.Business
      )
      
      SELECT Businesses.*, ISNULL(KeyBusinesses.KeyBusiness, Businesses.Business) AS KeyBusiness
      FROM Businesses
      LEFT JOIN KeyBusinesses ON Businesses.Business = KeyBusinesses.Business