【问题标题】:MySQL Selecting data, not repeating IDMySQL 选择数据,不重复 ID
【发布时间】:2020-06-11 20:47:50
【问题描述】:

我有 3 张桌子:

  1. 具有以下字段的工人:worker_id、姓名、姓氏、
  2. 具有以下字段的任务:task_id、tasks_name,
  3. 表实现,包含worker_id和task_id

我必须选择worker_idnamesurnametask_name。问题是我不知道如何在选择数据时不复制worker_id(我必须显示worker的所有任务)。

我想出了一个查询,但正如我之前提到的,它对我不起作用(它重复工人的 id)

SELECT workers.worker_id, workers.name, workers.surname, tasks.tasks_name 
FROM workers, tasks, implementing 
WHERE workers.worker_id=implementing.worker_id AND tasks.task_id=implementing.task_id

【问题讨论】:

  • 请提供样本数据和期望的结果。如果一个工作人员有多个任务,你想如何在一行中表示?
  • 这是 1980 年代使用的连接语法。你几岁???使用在 1992 年成为 SQL 标准的显式连接(inner joinleft outer join 等)。

标签: mysql sql join select group-by


【解决方案1】:

你会得到类似的东西

+-----------+------+---------+------------+ | worker_id |姓名 |姓氏 |任务名称 | +-----------+------+---------+------------+ | 1 |约翰 |史密斯 |任务 A | | 1 |约翰 |史密斯 |任务 B | | 2 |简 |米勒 |任务 C | +-----------+------+---------+------------+

这正是它应该的样子。 SQL 查询返回包含列和行的表。如果没有工人信息,一行的数据将是不完整的。您可以使用 CASE 表达式和解析 LAG 函数(自 MySQL 8 起可用)来抑制此操作,但您应该在显示数据的应用程序或网站中执行此操作。 (这也是您决定是否为小数点分隔符显示逗号或点的地方。)SQL 是数据提供者,您的应用关心表示。

无论如何,这是一个在 MySQL 8 中执行此操作的查询:

select 
  case when w.worker_id = lag(w.worker_id) over (order by w.worker_id, t.task_id) then null else w.worker_id end as worker_id,
  case when w.worker_id = lag(w.worker_id) over (order by w.worker_id, t.task_id) then null else w.name end as name,
  case when w.worker_id = lag(w.worker_id) over (order by w.worker_id, t.task_id) then null else w.surname end as surname,
  t.tasks_name
from workers w
join implementing i on i.worker_id = w.worker_id
join tasks t on t.task_id = i.task_id
order by w.worker_id, t.task_id;
+-----------+------+---------+------------+ | worker_id |姓名 |姓氏 |任务名称 | +-----------+------+---------+------------+ | 1 |约翰 |史密斯 |任务 A | | | | |任务 B | | 2 |简 |米勒 |任务 C | +-----------+------+---------+------------+

【讨论】:

  • 非常感谢您的帮助。这就是我想要得到的:)
【解决方案2】:

问题是我不知道如何在选择数据时不复制worker_id(我必须显示工人的所有任务)。

看起来你想要字符串聚合。您可以使用group_concat() 将每个工作人员的所有任务作为逗号分隔的列表放在单个列中。

您可以使用连接或相关子查询来执行此操作,如下所示:

select
    w.worker_id,
    w.name,
    w.surname,
    (
        select group_concat(t.task_name)
        from implementing i
        inner join tasks t on t.task_id = i.task_id
        where i.worker_id = w.worker_id
    ) task_names
from worker w

请注意,这使用标准的显式连接(使用 on 关键字)而不是老式的隐式连接(在 from 子句中使用逗号):这种几十年前的语法使查询更难遵循和维护,并且不应在新代码中使用。

【讨论】:

  • 为什么投反对票?这对我来说看起来非常好。 (无论如何,对答案投反对票而不解释原因是不礼貌的,而且根本没有帮助。)
猜你喜欢
  • 2011-09-07
  • 2015-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
相关资源
最近更新 更多