LATERAL

 

 

(8.0.34)
https://mita2db.hateblo.jp/entry/MySQL_8%E3%81%AE%E6%96%B0%E6%A9%9F%E8%83%BD_LATERAL%E5%8F%A5%E3%81%AB%E3%82%88%E3%82%8BSQL%E3%83%81%E3%83%A5%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0


-- 1. テストデータ作成

drop table tab2 ;
drop table tab1 ;

create table tab1(
    col1 bigint not null
   ,col2 varchar(100)
   );

create table tab2(
    col1 bigint not null
   ,col2 bigint not null
   ,col3 varchar(100)
   );

alter table tab1 add constraint tab1pk primary key(col1);
alter table tab2 add constraint tab2pk primary key(col1,col2);

alter table tab2 add constraint tab2fk foreign key(col1) references tab1(col1);

show create table tab1;
show create table tab2;


drop procedure proc1;

delimiter //
create procedure proc1()
begin
  declare i bigint;
  declare j bigint;
  start transaction;
  set i = 1;
  while i <= 100 do
    insert into tab1 values(i,substring(md5(rand()), 1, 30) );

    set j = 1;
    while j <= 10000 do
      insert into tab2 values(i,j,substring(md5(rand()), 1, 30) );
      set j = j + 1;
    end while;

    set i = i + 1;
  end while;
  commit;
end
//
delimiter ;

call proc1();

 

select count(*) from tab1;
select count(*) from tab2;

 

select * from tab1 order by rand() limit 10;
select * from tab2 order by rand() limit 10;


-- 2. 実行計画比較


explain format=tree
select 
  t1.col1 col1
, t1.col2 col2
, max(t2.col2) col2max
, min(t2.col2) col2min
from tab1 t1 inner join tab2 t2 
on t1.col1 = t2.col1 
group by t1.col1,t1.col2
order by t1.col1,t1.col2
;


(3.56 sec)

explain format=tree
select 
  t1.col1 col1
, t1.col2 col2
, t3.col2max
, t3.col2min
from tab1 t1 ,lateral
(select 
  max(t2.col2) col2max
, min(t2.col2) col2min
from tab2 t2
where t1.col1 = t2.col1
) t3
order by t1.col1,t1.col2
;

(0.27 sec)

explain format=tree
select 
  t1.col1 col1
, t1.col2 col2
, t3.col2max
, t3.col2min
from tab1 t1 cross apply
(select 
  max(t2.col2) col2max
, min(t2.col2) col2min
from tab2 t2
where t1.col1 = t2.col1
) t3
order by t1.col1,t1.col2
;

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'apply


explain format=tree
select 
  t1.col1 col1
, t1.col2 col2
,(select max(t2.col2) from tab2 t2 where t1.col1 = t2.col1) col2max
,(select min(t2.col2) from tab2 t2 where t1.col1 = t2.col1) col2min
from tab1 t1 
order by t1.col1,t1.col2
;

(0.48 sec)

 

 

(23c)

https://blogs.oracle.com/otnjp/post/tsushima-hakushi-37


-- 1. テストデータ作成

drop table tab1 cascade constraint;
drop table tab2 cascade constraint;

create table tab1(
    col1 int not null
   ,col2 varchar2(100)
   );

create table tab2(
    col1 int not null
   ,col2 int not null
   ,col3 varchar2(100)
   );

alter table tab1 add constraint tab1pk primary key(col1);
alter table tab2 add constraint tab2pk primary key(col1,col2);

alter table tab2 add constraint tab2fk foreign key(col1) references tab1(col1);


set long 4000000
set longchunksize 4000000
exec dbms_metadata.SET_TRANSFORM_PARAM(dbms_metadata.SESSION_TRANSFORM,'SQLTERMINATOR',true);

select dbms_metadata.get_ddl('TABLE','TAB1',user) from dual;
select dbms_metadata.get_ddl('TABLE','TAB2',user) from dual;


declare
begin
for i in 1..100 loop
  insert into tab1 values (i,substr(standard_hash(dbms_random.value(), 'MD5'),1,30) );

  for j in 1..10000 loop
    insert into tab2 values (i,j,substr(standard_hash(dbms_random.value(), 'MD5'),1,30) );
  end loop;

end loop;
end;
/

commit;

 


select count(*) from tab1;
select count(*) from tab2;

 

select * from tab1 order by dbms_random.value()  fetch first 10 rows only;
select * from tab2 order by dbms_random.value()  fetch first 10 rows only;


-- 2. 実行計画比較

set time on
set timing on


explain plan for
select 
  t1.col1 col1
, t1.col2 col2
, max(t2.col2) col2max
, min(t2.col2) col2min
from tab1 t1 inner join tab2 t2 
on t1.col1 = t2.col1 
group by t1.col1,t1.col2
order by t1.col1,t1.col2
;

select * from table(dbms_xplan.display(format=>'ALL') );

経過: 00:00:00.21


explain plan for
select 
  t1.col1 col1
, t1.col2 col2
, t3.col2max
, t3.col2min
from tab1 t1 ,lateral
(select 
  max(t2.col2) col2max
, min(t2.col2) col2min
from tab2 t2
where t1.col1 = t2.col1
) t3
order by t1.col1,t1.col2
;

select * from table(dbms_xplan.display(format=>'ALL') );

経過: 00:00:00.11


explain plan for
select 
  t1.col1 col1
, t1.col2 col2
, t3.col2max
, t3.col2min
from tab1 t1 cross apply
(select 
  max(t2.col2) col2max
, min(t2.col2) col2min
from tab2 t2
where t1.col1 = t2.col1
) t3
order by t1.col1,t1.col2
;

select * from table(dbms_xplan.display(format=>'ALL') );

経過: 00:00:00.11

 

explain plan for
select 
  t1.col1 col1
, t1.col2 col2
,(select max(t2.col2) from tab2 t2 where t1.col1 = t2.col1) col2max
,(select min(t2.col2) from tab2 t2 where t1.col1 = t2.col1) col2min
from tab1 t1 
order by t1.col1,t1.col2
;


select * from table(dbms_xplan.display(format=>'ALL') );

経過: 00:00:00.20

 

(16)
https://lets.postgresql.jp/documents/technical/lateral/1


-- 1. テストデータ作成

drop table tab1 CASCADE;
drop table tab2 CASCADE;

create table tab1(
    col1 bigint not null
   ,col2 varchar(100)
   );

create table tab2(
    col1 bigint not null
   ,col2 bigint not null
   ,col3 varchar(100)
   );

alter table tab1 add constraint tab1pk primary key(col1);
alter table tab2 add constraint tab2pk primary key(col1,col2);

alter table tab2 add constraint tab2fk foreign key(col1) references tab1(col1);

\d tab1
\d tab2

start transaction;

do $$
declare
begin

  for i in 1..100 loop
    insert into tab1 values(i,substring(md5(random()::text), 1, 30) );

    for j in 1..10000 loop
      insert into tab2 values(i,j,substring(md5(random()::text), 1, 30) );
    end loop;
    
  end loop;
end
$$
;

commit;

 

select count(*) from tab1;
select count(*) from tab2;


\pset pager 0

select * from tab1 order by random() limit 10;
select * from tab2 order by random() limit 10;


-- 2. 実行計画比較


explain analyze
select 
  t1.col1 col1
, t1.col2 col2
, max(t2.col2) col2max
, min(t2.col2) col2min
from tab1 t1 inner join tab2 t2 
on t1.col1 = t2.col1 
group by t1.col1,t1.col2
order by t1.col1,t1.col2
;

Execution Time: 388.292 ms


explain analyze
select 
  t1.col1 col1
, t1.col2 col2
, t3.col2max
, t3.col2min
from tab1 t1 ,lateral
(select 
  max(t2.col2) col2max
, min(t2.col2) col2min
from tab2 t2
where t1.col1 = t2.col1
) t3
order by t1.col1,t1.col2
;

Execution Time: 1.346 ms

explain analyze
select 
  t1.col1 col1
, t1.col2 col2
, t3.col2max
, t3.col2min
from tab1 t1 cross apply
(select 
  max(t2.col2) col2max
, min(t2.col2) col2min
from tab2 t2
where t1.col1 = t2.col1
) t3
order by t1.col1,t1.col2
;

ERROR:  "apply"またはその近辺で構文エラー


explain analyze
select 
  t1.col1 col1
, t1.col2 col2
,(select max(t2.col2) from tab2 t2 where t1.col1 = t2.col1) col2max
,(select min(t2.col2) from tab2 t2 where t1.col1 = t2.col1) col2min
from tab1 t1 
order by t1.col1,t1.col2
;


Execution Time: 1.371 ms

 

 

(2022)

https://interprism.hatenablog.com/entry/cross-apply-outer-apply-lateral

-- 1. テストデータ作成

drop table tab2 ;
drop table tab1 ;

create table tab1(
    col1 bigint not null
   ,col2 varchar(100)
   );

create table tab2(
    col1 bigint not null
   ,col2 bigint not null
   ,col3 varchar(100)
   );

alter table tab1 add constraint tab1pk primary key(col1);
alter table tab2 add constraint tab2pk primary key(col1,col2);

alter table tab2 add constraint tab2fk foreign key(col1) references tab1(col1);

sp_help tab1;
go

sp_help tab2;
go

 

set nocount on
declare @i int;
declare @j int;
begin transaction;
set @i = 1;
while @i <= 100
begin
  insert into tab1 values(@i,substring(master.dbo.fn_varbintohexstr(HASHBYTES('MD5',cast(rand() as varchar))),3,30) );
  
  set @j = 1;
  while @j <= 10000
  begin
    insert into tab2 values(@i,@j,substring(master.dbo.fn_varbintohexstr(HASHBYTES('MD5',cast(rand() as varchar))),3,30) );
    set @j = @j + 1;
  end
  
  set @i = @i + 1;
end
commit;

 

 

select count(*) from tab1;
select count(*) from tab2;


select top(10) * from tab1 order by newid();
select top(10) * from tab2 order by newid();


-- 2. 実行計画比較

set showplan_all on
go

set showplan_all off
go

set statistics time on
go

select 
  t1.col1 col1
, t1.col2 col2
, max(t2.col2) col2max
, min(t2.col2) col2min
from tab1 t1 inner join tab2 t2 
on t1.col1 = t2.col1 
group by t1.col1,t1.col2
order by t1.col1,t1.col2
;

経過時間 = 223 ミリ秒

select 
  t1.col1 col1
, t1.col2 col2
, t3.col2max
, t3.col2min
from tab1 t1 ,lateral
(select 
  max(t2.col2) col2max
, min(t2.col2) col2min
from tab2 t2
where t1.col1 = t2.col1
) t3
order by t1.col1,t1.col2
;

メッセージ 156、レベル 15、状態 1、行 7
キーワード 'select' 付近に不適切な構文があります。
メッセージ 102、レベル 15、状態 1、行 12
')' 付近に不適切な構文があります。


select 
  t1.col1 col1
, t1.col2 col2
, t3.col2max
, t3.col2min
from tab1 t1 cross apply
(select 
  max(t2.col2) col2max
, min(t2.col2) col2min
from tab2 t2
where t1.col1 = t2.col1
) t3
order by t1.col1,t1.col2
;

経過時間 = 1 ミリ秒


select 
  t1.col1 col1
, t1.col2 col2
,(select max(t2.col2) from tab2 t2 where t1.col1 = t2.col1) col2max
,(select min(t2.col2) from tab2 t2 where t1.col1 = t2.col1) col2min
from tab1 t1 
order by t1.col1,t1.col2
;


経過時間 = 0 ミリ秒