再帰CTE を使って遊ぼう 大阪#9 2012/04/14.

Slides:



Advertisements
Similar presentations
SQL データベースアクセスのための文法 担当 岡村耕二 月曜日 2限 平成20年度 情報科学III (理系コア科目・2年生)
Advertisements

SQLite3
インターネット技術特論 H:SQLite3 山口 実靖
情報理工学部 情報システム工学科 ラシキアゼミ 3年 H 井奈波 和也
データベース工学および演習 第5章 リレーショナルデータベース言語SQL
PostGIS - 1 (入門編).
SQL データベースアクセスのための文法と MySQL
2 分探索木 Binary Search Tree 実行可能な操作 計算量 木の高さは,最悪 O(n) n = |A| : 要素の個数
3-1 MySQLについて 発表者:藤村元彦 自然言語処理研究室.
3DCGコンテンツの基礎 第5回授業:最終課題制作
MySQLに接続するデータベースプログラム
2008年12月11日 RDBMSとSQL(2/3) 関数,GROUP,JOIN,演算
6-2 データベース 1.SQLite SQLを単純化した SQLite を使ってデータベースを操作 表「fruit」
ACCESSによる データベースアプリケーション開発実習 日本工業大学 情報工学科 “データベースの実際” 教材
Accessによる SQLの操作 ~実際にテーブルを操作してみよう!~.
SQL J2EE I 第3回 /
情報工学概論 (アルゴリズムとデータ構造)
プログラミング論 II RDBMSとSQL
3-2.データを取り出す 2004年 5月20日(木) 01T6074X 茂木啓悟.
T-SQL の Parse と Generate
MSBuild 色々出来るよ 2011/04/02 お だ.
Webコミュニケーショングループ ~CGI勉強会~ (データーベース編)
Tokuda Lab. NISHIMURA Taichi
ML 演習 第 7 回 新井淳也、中村宇佑、前田俊行 2011/05/31.
(B2) 親: minami, kazuki 多様な認証機器に対応する 認証システム (B2) 親: minami, kazuki.
パフォーマンスチューニング on Rails
14.テーブル定義,一対多の関係,多対多の関係, 外部キー,索引(インデックス),データベース操作
table 'results' SELECT name, teacher FROM results;
マイクロソフト Access での SQL 演習 第1回 SQL問い合わせ(クエリ)
   年  月  日 名前 太郎 1 班 2011/6/10.
   年  月  日 名前 太郎 1 班.
2004/05/13 3-4 データ型(カラムタイプ) について 発表者:藤村元彦 自然言語処理研究室.
SQL パフォーマンス チューニング ~ カバーリングインデックス/クエリヒントの利用~
データベースを使ったプログラミング ~JDBCを使ってみよう~
Oracle XEを使ってみよう 初音玲.
SQL データベースアクセスのための文法 担当 岡村耕二 月曜日 2限 平成21年度 情報科学III (理系コア科目・2年生)
第2回.リレーショナルデータベース入門 SQL を用いたテーブルへの行の挿入 SQL 問い合わせの発行と評価結果の確認.
3-10. MySQLシステムの管理  2004年6月10日  大北高広                01T6010F.
第1回.リレーショナルデータベースを使ってみよう
第1回.リレーショナルデータベースを使ってみよう
第2回.リレーショナルデータベース入門 SQL を用いたテーブルへの行の挿入 SQL 問い合わせの発行と評価結果の確認.
SQL パフォーマンス チューニング ~ プランガイドの利用~
Windows Azure (CTP) 触ってみた
暗黙的に型付けされる構造体の Java言語への導入
マイクロソフト Access での SQL 演習 第5回 副問い合わせ
第3回.テーブルの結合 結合条件 SQL を用いた結合問い合わせ.
第3回.テーブルの結合 結合条件 SQL を用いた結合問い合わせ.
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
3-6.インデックスについて 3-7.関数と併用されることの 多いMySQLコマンド
3-3.テーブルを更新する 2004年 4月22日(木) 01T6074X 茂木啓悟.
「Webデータベースの構築技術」正誤表 ページ 項目 誤記 訂正 18 表1.4 アクセス 権限の削除 ・・・テーブル名 TO ユーザ名
マイクロソフト Access での SQL 演習 第4回 並べ替え(ソート)
講義ノート共有データベース NoteTotter?
テーブル設計を後から変更 現場で使える小技のご紹介 株式会社ジーワンシステム 生島 勘富(イクシマ サダヨシ)
Windows Azure (CTP) 触ってみた
Oracle XEを使ってみよう 初音玲.
マイクロソフト Access での SQL 演習 第2回 集計,集約
~let's take fun when you can do it~
3-8・関数を使ってデータを取り出す   2004年6月3日(木) 01T6010F               大北高広.
3.リレーショナルデータベース,主キー, SQL
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
関係データベースとSQL MZ Platform講習会(上級).
09 06/23 PHP と SQL (MySQL) の連携 その3
第2回.リレーショナルデータベース入門 SQL を用いたテーブルへの行の挿入 SQL 問い合わせの発行と評価結果の確認.
第1回.リレーショナルデータベースを使ってみよう
SQL J2EE I (データベース論) 第3回 /
情報処理Ⅱ 小テスト 2005年2月1日(火).
クリエイティブ リサーチ 2019/05/20 日本工学院八王子専門学校 M.Katsube.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
SQL データベース論 第11回.
Presentation transcript:

再帰CTE を使って遊ぼう 大阪#9 2012/04/14

自己紹介 織田 信亮(おだ しんすけ) 大阪で開発者しています SQLWorld の代表です http://d.hatena.ne.jp/odashinsuke/ Twitter:@shinsukeoda

再帰CTE って何? 共通テーブル式(Common Table Expression)を用いた再帰クエリの事 CTE は 共通テーブル式の略

じゃあ 共通テーブル式って何? 共通テーブル式の使用 一時的な結果セットに名前を付けたもの http://msdn.microsoft.com/ja-jp/library/ms190766.aspx 一時的な結果セットに名前を付けたもの 一時的なので、クエリが実行している間しか保持しません。 派生テーブルに似ている。 派生テーブル:サブクエリ

CTE の構文と使用例 WITH を使って、クエリに名前を付けて使い回し出来る。 WITH expression_name [ ( column_name [,...n] ) ] AS ( CTE_query_definition ) with [CTE] ([SDATE]) as (select GETDATE()) , [CTE2] ([SDATE2]) as (select GETDATE()) select * from [CTE], [CTE2]

サブクエリと何が違うの? 同じクエリ内で複数回参照出来る select * from (select GETDATE() as [SDATE]) [CTE], (select GETDATE() as [SDATE2]) [CTE2] with [CTE] ([SDATE]) as (select GETDATE()) select * from [CTE] , [CTE] as [CTE2]

注意点など (1) CTE は複数作成可能 (“,” 区切り) 物理テーブル名と同じ名前はOK CTE の名前は重複NG create table [テーブル] ( [Id] int not null primary key ) GO with [テーブル] ([今]) as ( select GETDATE() select * from [テーブル] -- GETDATE の結果が取れる drop table [テーブル]

注意点など (2) クエリは、View の作成と同じ要件 同一 WITH で先に定義した CTE は参照可能 with [テーブル] as ( select GETDATE() as [今] ), [テーブル2] as ( select [今], [今] - 1 as [ちょっと前] from [テーブル] ) select * from [テーブル2], [テーブル]

注意点など (3) 列名は、重複NG 列名の数は、結果セットの列数と同じ 結果セット内の列名が全て異なる場合は、列名の省略可能 with [テーブル] ([今], [ちょっと前]) as ( select GETDATE() as [今], GETDATE() - 1 as [今] ) select * from [テーブル] GO with [テーブル] as ( select GETDATE() as [今], GETDATE() - 1 as [ちょっと前]

注意点など (4) CTE の直前にステートメントがある場合は、末尾に “;” が必要 CTE を参照出来るのは、直後のステートメントのみ with [テーブル] as ( select GETDATE() as [今], GETDATE() - 1 as [ちょっと前] ) select GETDATE() select * from [テーブル] -- エラーになる

使いどころ 1クエリ内で、同じサブクエリを複数回使いたい サブクエリが長すぎて見にくいから、分割したい

サブクエリと違うところがまだある! 自己参照が可能 UNION ALL 演算子を使うと自己参照出来る with [CTE] ([LEVEL]) as ( select 1 as [LEVEL] union all select [CTE].[LEVEL] + 1 from [CTE] ) select top(100) [LEVEL] from [CTE]

再帰CTE

階層構造のデータを取得(親 – 子)

create table [dbo].[階層テーブル]( [Id] [int] identity(1,1) primary key, [Name] [nvarchar](50) not null, [ParentId] [int] null ) insert into [階層テーブル] ([Name], [ParentId]) values ('地球', null), ('日本', 1), ('日本以外', 1), ('近畿', 2), ('大阪', 4), ('京都', 4), ('兵庫', 4), ('関東', 2), ('東京', 9), ('神奈川', 9), ('埼玉', 9), ('ミラノ', 3), ('ローマ', 3), ('ロンドン', 3)

with [CTE] ([Id], [Name], [ParentId], [Path]) as ( select [Id], [Name], null, cast([Name] as nvarchar(4000)) as [Path] from [dbo].[階層テーブル] where [ParentId] is null union all select [階層テーブル].[Id], [階層テーブル].[Name], [階層テーブル].[ParentId], [CTE].[Path] + N' - ' + [階層テーブル].[Name] from [dbo].[階層テーブル] inner join [CTE] on [dbo].[階層テーブル].[ParentId] = [CTE].[Id] ) select * from [CTE]

階層構造のデータを取得(子 – 親)

with [CTE] ([Id], [Name], [ParentId], [Path]) as ( select [Id], [Name], [ParentId], cast([Name] as nvarchar(4000)) as [Path] from [dbo].[階層テーブル] where [Id] = 5 union all [階層テーブル].[Id], [階層テーブル].[Name], [階層テーブル].[ParentId], [CTE].[Path] + N' - ' + [階層テーブル].[Name] from [dbo].[階層テーブル] inner join [CTE] on [dbo].[階層テーブル].[Id] = [CTE].[ParentId] ) select * from [CTE]

連番表の作成 これをうまく使うと… with [CTE] ([LEVEL]) as ( select 1 as [LEVEL] union all select [CTE].[LEVEL] + 1 from [CTE] ) select top(100) [LEVEL] from [CTE]

再帰クエリでデータ作成

create table [テスト] ( [Id] int identity(1, 1) primary key, [名前] nvarchar(30), [分割件数] int not null ) insert into [テスト] ( [名前], [分割件数] ) values ('10個に増やす', 10), ('5個に増やす', 5), ('1個のまま', 1), ('3個に増やす', 3)

with [CTE](行連番) as ( select 1 union all select [行連番] + 1 from [CTE] ) select [テスト].[Id] , [テスト].[名前] , [テスト].[分割件数] , [DUMMY].[行連番] from [テスト] inner join ( select top ((select max([テスト].[分割件数]) from [テスト])) [行連番] from [CTE] ) [DUMMY] on [DUMMY].[行連番] <= [テスト].[分割件数] order by option (MAXRECURSION 0)

連番以外でも… カレンダーテーブルや、毎週/月/年、隔週/月/年 のデータもすぐ作成可能 with [CTE] ([日付]) as ( select GETDATE() as [日付] union all select DATEADD(day, 1, [日付]) from [CTE] ) select top (10) [日付] from [CTE]

注意点 再帰出来る上限回数が決まっています 上限を超えると、それまでの結果とエラーが返る 既定値 は 100回 上限回数を明示的に指定するには、クエリヒントの MAXRECURSION を指定する OPTION MAXRECURSION(<number>) 0 を指定すると、無制限