MySQL子查询奇怪问题

huangapple go评论59阅读模式
英文:

MySQL subquery strange issue

问题

MySQL: 5.7.16

有两个表:

  1. rule_conf 表:
CREATE TABLE `rule_conf`  (
  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `app_id` bigint(20) UNSIGNED NOT NULL,
  `app_log_id` bigint(20) UNSIGNED NOT NULL,
  `r_type` tinyint(2) UNSIGNED NOT NULL,
  `r_status` tinyint(2) UNSIGNED NOT NULL DEFAULT 0,
   ...
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_app_log_id`(`app_log_id`) USING BTREE,
  INDEX `idx_app_id`(`app_id`) USING BTREE
) ENGINE = InnoDB
  1. app_log_conf 表:
CREATE TABLE `app_log_conf`  (
  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `app_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
   ...
  INDEX `idx_app_id`(`app_id`) USING BTREE
) ENGINE = InnoDB

有一个 SQL 查询语句:

select app_id from rule_conf
where app_log_id = (
   select max(id) from app_log_conf where app_id = 123 and r_status = 1 and r_type = 1
) 

这个 SQL 返回一个空结果,没有抛出错误,为什么?

按照我的预期,这个 SQL 应该会抛出一个 Unknown Column 的异常,但实际上没有。

当我在子查询中添加了一个条件 aaa = 1 后,然后执行整个 SQL,我得到了一个错误:1054 - Unknown column 'aaa' in 'where clause,这是我预期的,因为表 app_log_conf 确实没有包含列 aaa

而当我单独执行子查询时,我得到了一个错误:1054 - Unknown column 'r_status' in 'where clause,这也是我的预期。

有可能是因为主查询中的表 rule_conf 包括了这些列吗?

所以,有人遇到过这样的问题吗?或者有人能解释一下为什么会这样吗?

英文:

MySQL: 5.7.16

There are two tables:

  1. rule_conf table:
CREATE TABLE `rule_conf`  (
  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `app_id` bigint(20) UNSIGNED NOT NULL,
  `app_log_id` bigint(20) UNSIGNED NOT NULL,
  `r_type` tinyint(2) UNSIGNED NOT NULL,
  `r_status` tinyint(2) UNSIGNED NOT NULL DEFAULT 0,
   ...
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_app_log_id`(`app_log_id`) USING BTREE,
  INDEX `idx_app_id`(`app_id`) USING BTREE
) ENGINE = InnoDB
  1. app_log_conf table:
CREATE TABLE `app_log_conf`  (
  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `app_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
   ...
  INDEX `idx_app_id`(`app_id`) USING BTREE
) ENGINE = InnoDB

There is a SQL:

select app_id from rule_conf
where app_log_id = (
   select max(id) from app_log_conf where app_id = 123 and r_status = 1 and r_type = 1
) 

this SQL return an empty result, not throw an error, WHY?

In my expectation, this SQL should throw an exception like Unknown Column, but it did not.

When I add a condition in subquery aaa = 1, then executing the holistic SQL, I got an Error: 1054 - Unknown column 'aaa' in 'where clause, that's my expectation, because table app_log_conf indeed not including column aaa.

And when I executing the subquery separately, I got an Error: 1054 - Unknown column 'r_status' in 'where clause, that's also my expectation.

Is there any possibility because the table 'rule_conf' in main query including those columns?

So, anyone encountered such issue, or can someone explain WHY?

can someone explain why

答案1

得分: 3

子查询知道主查询的列。如果在主查询表和子查询表中有相同的列名,并且您没有在子查询中指定要使用哪一个,那么子查询表的列将优先于主查询表的列。因此,您的查询可以翻译为:

select rule_conf.app_id 
from rule_conf
where rule_conf.app_log_id = 
(
  select max(app_log_conf.id)
  from app_log_conf
  where app_log_conf.app_id = 123
  and rule_conf.r_status = 1
  and rule_conf.r_type = 1
);

当涉及多个表时,您应该在所有列名前加上它们所属的表,以避免错误。使用别名可以帮助解决这个问题。

子查询知道主查询的列有时是必要的,特别是当我们想要编写一个相关子查询时,例如:

select rc.app_id 
from rule_conf rc
where rc.app_log_id = 
(
  select max(alc.id)
  from app_log_conf alc
  where alc.app_id = rc.app_id
);
英文:

The subquery knows the columns of the main query. If there is the same column name in your main query table and your subquery table and you don't qualify which you want in the subquery, the subquery table's column has precedence over the main query table's one. Your query hence translates to:

select rule_conf.app_id 
from rule_conf
where rule_conf.app_log_id = 
(
  select max(app_log_conf.id)
  from app_log_conf
  where app_log_conf.app_id = 123
  and rule_conf.r_status = 1
  and rule_conf.r_type = 1
);

When working with more than one table, you should qualify all column names with their table in order to avoid mistakes. Using alias table names helps with this.

That the subquery knows the columns of the main query is necessary sometimes, when we want to write a correlated subquery, e.g.

select rc.app_id 
from rule_conf rc
where rc.app_log_id = 
(
  select max(alc.id)
  from app_log_conf alc
  where alc.app_id = rc.app_id
);

huangapple
  • 本文由 发表于 2023年7月20日 18:25:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76728932.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定