【问题标题】:Is there a good way to get children in MySQL as an array?有没有一种好方法可以让 MySQL 中的孩子作为一个数组?
【发布时间】:2021-09-30 21:30:19
【问题描述】:

首先,抱歉,如果这是重复的,我真的不知道这个问题的最佳术语。

假设我有代表的 SQL 架构:

Businesses:
id: int
name: string

Employees:
id: int
business_id: int REFERENCES Businesses(id)
name: string

是否有任何可以想象的方法可以查询一个企业列表,每个企业都有一组员工作为字段附加?目前,我正在将企业列表拉入我的服务器,然后对于阵列中的每个企业,获取所有 business_id 等于其 id 的员工。这行得通,但对于大量企业而言,它会导致对数据库的大量查询。

我考虑的另一个选择是将所有员工读入我服务器上的内存,将它们放入[business_id->[employees]] 的映射中,然后将员工数组发送到服务器上正确的企业employees 字段。这似乎是一个性能更高的选项,但我想知道 MySQL 中是否有任何内置功能可以让我开箱即用地执行此操作,因为这似乎是一项非常常见的任务。谢谢!

编辑: @MatBailie 在这里提出了关于代码异味的观点,我只是想澄清这段代码的总体意图。我将从高级别添加逐步演练。

  1. 从列表中选择所有公司
  2. 获取每家公司的所有员工
  3. 向用户显示公司列表,并在每个公司旁边显示每位员工的可滚动列表

我知道,正如@radocaw 所指出的,获取企业的员工列表是一个微不足道的连接,但我的问题是这将需要多次访问数据库。我将在下面的 Golang 中发布我当前解决此问题的方法,使用 MySQL 中的两个简单 SELECT 和使用映射。这是给你的,@Tangentially Perpendicular!

    employeeMap := make(map[int][]Employee)
    employees,err := db.Query("SELECT business_id,f_name,l_name,email FROM employees")
    if err != nil {
        //handle error
    }
    for employees.Next(){
        var employee Employee
        err = employees.Scan(&employee.BusinessId,&employee.FName,&employee.LName,&employee.Email)
        if err != nil {
            //handle error
            continue
        }
        if _,ok := employeeMap[employee.BusinessId];ok{
            employeeMap[employee.BusinessId] = append(employeeMap[employee.BusinessId],employee)
        }else {
            employeeMap[employee.BusinessId] = make([]Employee,1)
            employeeMap[employee.BusinessId[0] = employee
        }
    }

这用于构建业务 ID 到员工列表的映射。接下来,我将从数据库中获取企业,并为其 id 附加该员工数组。

我不确定这是否是一个好方法,但它似乎比使用 n 连接访问数据库更优化和直接,其中 n是企业的数量。感谢大家的精彩反馈和高质量的答案/cmets!

【问题讨论】:

  • 您可能需要检查stackoverflow.com/questions/97197/…,它将您的问题描述为“N+1 SELECT”问题
  • 这可以通过两个表之间的简单JOIN 很好地解决,所有这些都在一个查询中。您将获得每个企业的 N 行,每个员工一个,您可以在客户端将其操作到一个数组中。 SQL中没有数组的概念。
  • @Alejandro 这很有趣,我不确定这种方法是否比我建议的映射到数组的方法更好或更差。我不确定 SQL 是否有任何子表的概念,我知道我已经看到它们由子查询返回,但不是作为列值。感谢您的确认!
  • @Progman +1 提醒我这叫什么。我认为,不管我怎么做,一次读取而不是每次读取的想法更好。
  • 当你得到这些数据后你打算做什么?关注最终结果并编写查询来实现这一目标,而不是中间步骤。这里的许多嵌套查询问题都是从尝试跨表检索数据开始的,但可以通过在数据库服务器上正确使用 JOIN 和聚合函数来解决。您可能会发现,对于某些查询,您根本不需要检索基础数据。

标签: mysql go


【解决方案1】:

这里有几个微妙不同的问题。

第一个是:

  1. 有没有一种好方法可以将 MySQL 中的子元素作为数组获取?

答案:可能有办法——但它不可能是“好”的。

第二个是:

  1. 是否有任何可行的方法可以查询一个企业列表,每个企业都将一组员工作为字段附加?

答案:在规范化的环境中,很难想象一个企业列表会有“作为一个字段附加的一组员工”

第三个可能是:

  1. 在标准化环境中,我如何将企业列表拉入我的服务器,然后为每个给定企业获取该企业所有员工的列表。

答案:这是一个简单的练习,通常使用 JOIN。如需更多帮助,请参阅https://stackoverflow.com/help/minimal-reproducible-example

【讨论】:

    【解决方案2】:

    您可以通过使用 group_concat 返回一个 CSV 列表来实现接近目标:

    SELECT b.id,b.name,group_concat(e.id) employee_ids, group_concat(e.name) employee_names 
    FROM businesses b 
    LEFT JOIN employees e on b.id = e.business_id 
    GROUP BY b.id,b.name
    

    然后在代码中将值拆分为数组。

    【讨论】:

    • 这很酷,我会在周一上班的时候测试一下,如果它有效,我会接受它作为答案,因为它准确地回答了问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    • 2010-09-17
    相关资源
    最近更新 更多