首页 > 解决方案 > sql中join语句如何执行

问题描述

我正在尝试从用户表中获取数据,以便每一行都包含日期值(非空)。如果值为空,则应查看具有相同 id 的上述日期 id 的列。不更新表行,仅使用 select 语句?

这是桌子

NAME, DATE, ID
A, 2021-01-21, 1
B, null, 1
C, null, 1
D, 2021-01-18, 2
D, null, 2

它应该被视为

A, 2021-01-21, 1
B, 2021-01-21, 1
C, 2021-01-21, 1
D, 2021-01-18, 2
D, 2021-01-18, 2

现在我认为的查询是=>

select t1.name, t2.date ,t1.id from user t1 
left join (select id ,date from user where id=1) t2 
on t1.id=t2.id;

但是这个查询不像我想的那样工作。

谁能告诉我上面的连接查询是如何工作的?我该如何改进它?这样我就得到了所需的结果。

对于上述查询的测试,请使用此查询 =>

create table user(
 name varchar(20),
 date date,
 id integer
);
insert into user values("A",'2021-01-21',1);
insert into user values("",null,1);
insert into user values("",null,1);
insert into user values("",null,1);
insert into user values("",null,1);
insert into user values("",null,1);
insert into user values("B",'2021-01-20',2);

select t1.name, t2.date ,t1.id from user t1 
left join (select id ,date from user where id=1) t2 
on t1.id=t2.id;

标签: mysqlsql

解决方案


第一个问题是您要在条件 上加入一个表t1.id = t2.id。因此,如果您有 4 行id=1和 3 行,id=2仅作为示例,您最终将得到 4 * 4 + 3 * 3 = 25 行的结果。在您的具体情况下,您最终将得到 6 * 6 + 1 * 1 = 37 行。

第二个问题是您id=1在子查询中进行了硬代码选择:

(select id ,date from user where id=1) t2

这不是所有可能行的适当值。

可以试试显而易见的:

select
   t1.name,
   ifnull(t1.date, (select t2.date from user t2 where t2.date is not null and t2.id = t1.id limit 1)) as date,
   t1.id
from user t1
;

见分贝小提琴

姓名 ID 日期
一种 1 2021-01-21
1 2021-01-21
1 2021-01-21
1 2021-01-21
1 2021-01-21
1 2021-01-21
2 2021-01-20

但更好的是使用连接:

select u.name, ifnull(u.date, sq.date) as date, u.id
from user u join (
    select id, min(date) as date from user group by id
) sq on u.id = sq.id
;

见分贝小提琴

我希望使用连接的第二个版本更有效,因为第一个版本有一个依赖子查询,必须为具有空日期的每一行执行。


推荐阅读