【问题标题】:Is this SQL statement valid, or is MySQL right to report an error?这个SQL语句是有效的,还是MySQL正确的报错?
【发布时间】:2021-08-07 02:47:05
【问题描述】:

我有一个带有子查询的查询,其中子查询单独在 MySQL 中正确运行,但整个查询会产生错误。我已经将问题提炼成一个简单的可重现的:

这是在 MySQL ERROR 1060 (42S21): Duplicate column name 'id' 中产生错误的查询

SELECT a.* FROM (
    SELECT * FROM locations l
       RIGHT JOIN total_cases c
               ON l.id=c.loc_id) a;

只运行子查询,

SELECT * FROM locations l
   RIGHT JOIN total_cases c
           ON l.id=c.loc_id;

产生结果

+------+----------------+------+--------+------------+-------------+
| id   | location       | id   | loc_id | date       | total_cases |
+------+----------------+------+--------+------------+-------------+
|  237 | United Kingdom |    1 |    237 | 2020-05-09 |      203171 |
|  237 | United Kingdom |    2 |    237 | 2020-05-10 |      206234 |
|  237 | United Kingdom |    3 |    237 | 2020-05-11 |      208391 |
...

我从 RDBMS 的角度感兴趣。重复的 id 列是否作为连接的结果有效,但在 SELECT 语句的列列表中无效?如果有人也可以提供标准参考,我将不胜感激。

编辑:关于如何重建查询的投票和答案表明我的问题不清楚。我想了解从 RDBMS 的角度什么是正确的行为,以及子查询和外部查询中重复列之间的区别。这是一个数据库问题,而不是“如何编写我的 sql”问题。谢谢!

【问题讨论】:

  • 作为连接结果的重复 id 列是否有效 否。MySQL 扩展允许在输出列表中这样做(歧义是客户端的问题,需要通过它们的引用来引用这些列占有指数)。但是子查询输出中的这种歧义是 MySQL 问题,它没有拥有引用 - 所以它会产生错误。
  • 是的,大多数 RDBMS 都会产生类似的错误,因为列名不明确。例如,MS SQL Server 给出“错误列 'Id' 为 'a' 指定了多次。
  • @Akina MySQL 扩展。好的,那么子查询应该在符合标准的数据库中也会出错吗?
  • 所以子查询在符合标准的数据库中也应该出错?是的

标签: mysql sql database join rdbms


【解决方案1】:

id 在两个表中,所以你现在可以决定

如果您需要所有列

SELECT a.* FROM (
    SELECT l.*,c.* FROM locations l
       RIGHT JOIN total_cases c
               ON l.id=c.loc_id) a;

或者,如果您不想从 bith 表中获得欺骗

SELECT a.* FROM (
    SELECT l.location ,c.* FROM locations l
       RIGHT JOIN total_cases c
               ON l.id=c.loc_id) a;

Mysql 无法为你决定你想要和需要哪个,所以你必须告诉他。

单独的子查询和他的 SELECT * 只作为结果集,但是当你尝试使用它作为 OUT 查询的基础时,它变成了一个临时表,它有一定的规则,其中一个规则是每一列都必须有它的自己的名字,要正确识别

【讨论】:

  • 谢谢,但问题是关于子查询中重复列的有效性
【解决方案2】:

在您的内部查询中使用别名,这样您就不会在外部查询中有两列名称相同 id

内部查询是宽松的,它假设您正在做一个测试

外部查询执行内部查询。并在执行时找到两列相同的column_name

让我用一个例子来说明。

假设您有一所学校,并且该学校有两个标有标签的教室 同名。像 class 4Aclass 4A 。那不是一个 到那时为止的问题。当您要发送时出现问题 一个学生去拜访class 4A。学生会带着 一个错误 。 “先生,您说的是哪个class 4A?”

建立和标注类没问题,但是执行时出现问题

SELECT a.* FROM (    SELECT      
 l.id as location_id,
 l.location,
 c.id as case_id,
 c.loc_id,
 c.date,
 c.total_cases FROM locations l
RIGHT JOIN total_cases c
       ON l.id=c.loc_id) a;

【讨论】:

  • 这是对的,但是您没有解释为什么一个有效而子查询无效。你可以更清楚一点。
  • 当然。让我加更多的肉
【解决方案3】:

https://dev.mysql.com/doc/refman/8.0/en/derived-tables.html

派生表是在查询 FROM 子句范围内生成表的表达式。例如,SELECT 语句 FROM 子句中的子查询是派生表

然后它说

派生表中的任何列都必须具有唯一的名称

【讨论】:

  • 这是正确答案。我们都知道有一个重复的列。这说明了为什么它在一种情况下有效,而在另一种情况下无效。
【解决方案4】:

子查询返回两个具有完全相同名称的列,id。当您尝试从中选择作为子查询时,它不知道它需要引用哪个 id。您需要在子查询中声明列名,并确保没有重复的列名。

【讨论】:

  • 谢谢,但问题是关于子查询中重复列的有效性
  • 实际上,这确实回答了有效性。它适用于一个查询,因为它只是输出所有列,但在您的嵌套查询中,它输出到另一个需要唯一列名的查询。
猜你喜欢
  • 2020-03-01
  • 2011-02-25
  • 2020-10-04
  • 1970-01-01
  • 2011-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多