SQLのJoinの使用詳細

6031 ワード

一.基本概念
sql文の中の接続(join)キーワードについては、一般的で分かりにくいキーワードです。以下の例では、C建表user 1、user 2を簡単に説明します。
テーブル1:create table user 2(id int,user_)name varhar(10)、over varhar(10);
insert into user 1 values(1、‘tangseng’、‘dtgdf’);
insert into user 1 values(2,‘sunwukeong’,‘dzsf’)
insert into user 1 values(1、‘zhubajie’、‘jtsz’)
insert into user 1 values(1,‘sharing’,‘jslah’);
テーブル2:create table user 2(id int,user_)name varhar(10)、over varhar(10);
insert into user 2 values(1、‘sunwukeong’、‘chenfo’)
insert into user 2 values(2,‘niumowang’,‘chengyao’);
insert into user 2 values(3、‘jiaomowang’、‘chengyao’);
insert into user 2 values(4、‘pengmowang’、‘chenyao’);
SQL標準におけるJoinのタイプ

1.内部接続(inner joinまたはjoin)
(1)概念:内連結は、述語の接続に基づいて2つの表の列を結合し、新しい結果表を生成する。
(2).内部接続の維恩図:

(3).sql文
select a.id,a.user_name,b.over from user 1 a inner join user 2 b on a.user_name=b.user_name
結果:

2.外部接続
外連結は左外向連結、右外向連結または完全外部連結を含みます。
a.左外接続:left joinまたはleft outerjin
(1)概念:左外向連結の結果集は、LEFT OUTER子文に指定された左表のすべての行を含み、連結列に一致する行だけではない。左の表のある行が右の表に行にマッチしていない場合、関連する結果の行の右の表のすべての選択リスト列は空の値(null)となります。
(2)左外部接続ウェン図:

(3)sql文:
select a.id,a.user_name,b.over from user 1 a left join user 2 b on a.user_name=b.user_name
結果:

b.右外接続:ライトジョインまたはライトアウトジョイン
(1)右外向接続は左外向接続の逆連結です。右の表のすべての行を返します。右の表のある行が左の表で行にマッチしていない場合、左の表に空の値を返します。
(2)右外接続ウェン図:

(3)sql文
select b.user_name,b.over,a.over from user 1 a right join user 2 b on a.user_name=b.user_name
結果:

c.全外接続:フルジョインまたはフルアウトジョイン
(1)外部連結を完全に行い、左と右の表のすべての行を返します。他のテーブルに行が一致していない場合、他のテーブルの選択リスト列に空の値が含まれます。テーブル間にマッチする行がある場合は、結果の行全体にベーステーブルのデータ値が含まれます。
(2)右外接続ウェン図:

(3)sql文
select a.id,a.user_name,b.over from user 1 a full join user 2 b on a.user_name=b.user_name
mysqlで全接続会报1064のエラーを调べると、mysqlは全接続クエリをサポートしていません。代替文:
select a.user_name,a.over,b.over from user 1 a left jin user 2 b on a.user_name=b.user_name union all select b.user_name,b.over,a.over from user 1 a right join user 2 b on a.user_name=b.user_name
結果:

3.デカルト接続(交差接続)
1.概念:WHERE子文のない交差接続は連結に関する表のデカルト積を発生します。第一の表の行数に第二の表の行数をかけると、デカルト積結果集の大きさになります。user 1とuser 2が交差して4*4=16個のレコードを生成します。
2.クロス接続:cross join(条件onなし)
3.sql文:
select a.user_name,b.user_name,a.over,b.over from user 1 a cross join user 2 b;
二.テクニックを使う
1.ジョンを使って表を更新する
以下の文を使って、user 1テーブルとuser 2テーブルに同時に存在するoverフィールドを「qtda」に更新します。
udate user 1 set over='qtds'where user 1.user_name in(select b.user_)name from user 1 a inner join user 2 b on a.user_name=b.user_name;
この文はsql server、oraceでは正しく実行できますが、mysqlではエラーが発生しました。mysqlでは更新子クエリのテーブルがサポートされていません。次の文を使ってできます。
udate user 1 a join(select b.user_)name from user 1 a join user 2 b on a.user_name=b.user_name)b on a.user_name=b.user_name set a.over='qtds'
2.joinを使ってサブクエリを最適化する
サブクエリの効率が悪いので、以下の文を使ってクエリーを行います。
select a.user_name,a.over,(selectover from user 2 b)where a.user_name=b.user_name)as over 2 from user 1 a;
joinを使ってサブクエリを最適化すると、同じ効果が得られます。
select a.user_name,a.over,b.over as over 2 from user 1 a left join user 2
b on a.user_name=b.user_name
3.ジョインを使って集約子クエリを最適化する
新しい表を紹介します。user_キラス
create table user_キラスid int、timestr varrhar(20)、kills int(10);
insert into user_kills values(2、‘2015-5-12’、20)
insert into user_kills values(2、‘2015-5-15’、18);
insert into user_kills values(3、‘2015-5-11’、16)
insert into user_kills values(3、‘2015-5-14’、13)
insert into user_kills values(3、‘2015-15-16’、17)
insert into user_kills values(4、‘2015-5-12’、16)
insert into user_kills values(4、‘2015-5-10’、13)
お問い合わせはuser 1の中で、お一人様user_に対応しています。kills表の中でkillsの最大の日付は、集約子クエリ文を使用します。
select a.user_name,b.timestr,b.kills from user 1 a join user ukills b on a
.id=b.user_id where b.kills=(select MAX(c.kills)from user_kills c where c.user_id=b.user_id)
ジョインを使用して、アグリゲートされたサブクエリを最適化する(サブクエリを避ける)。
select a.user_name,b.timestr,b.kills from user 1 a join user ukills on
a.id=b.user_id join user_kills c on c.user_id=b.user_id group by a.user_name、b.timestr、b.kills having b.kills=max(c.kills)
結果:

4.パケット選択データの実現
アメリカ人一人当たりのキラスペアの多い2日間を検索してください。
まず、次の文を通じて、ある人のkillsが一番多い二日間を調べられます。
select a.user_name,b.timestr,b.kills from user 1 a join user ukills on
a.id=b.user_id where a.user_name='sunwukoong'order by b.kills desc limit 2;
では、どのようにして全員のkillsの一番多い二日間を調べられますか?次の文を見てください。
WITH tmp AS(select a.user_name,b.timestr,b.kills,ROW_NUMBER()over(partition by a.user_name order by b.kills)cnt from user 1 a join user ukills b on a.id=b.user_id)select*from tmp where cnt<=2;
上記の文はsql serverとoracleでサポートされていますが、mysqlはパケット並び替え関数ROW_をサポートしていません。NUMBER()は、以下で代替方法を提供する。
select d.user_name,c.timestr,kills fromid,timestr,kills,from user_kills b where b.user_id=a.user_id and a.kills<=b.kills)as cnt from user_kills a group by user_id,timestr,kills)c join user 1 d on c.user_id=d.id where cnt==2;
結果:

ここでSQLのJoinに関する詳細な文章を紹介します。もっと関連するSQLのJoinの内容は以前の文章を検索してください。または下記の関連記事を引き続きご覧ください。これからもよろしくお願いします。