这条SQL语句是否有效,还是MySQL正确报错?

时间:2021-05-17 20:13:28

标签: mysql sql database join rdbms

我有一个带有子查询的查询,其中子查询单独在 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”问题。谢谢!

4 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

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

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

然后它说

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

答案 2 :(得分:0)

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

如果您需要所有列

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

或者,如果你不想从比特表中得到欺骗

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 查询的基础时,它变成了一个临时表,它有一定的规则,其中之一是每列都必须有它的自己的名字,要正确识别

答案 3 :(得分:0)

在内部查询中使用别名,这样外部查询中不会有两列同名 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;