2013年4月7日日曜日

◆実践編:3つ以上の テーブルの結合

この STEP で使用するデータベース

この STEP では、サンプル スクリプトに含まれる「NorthwindJ 」データベース
(NorthwindJ.mdf と NorthwindJ.ldf)を利用します。この STEP を始める前に、このデータベ
ースを SQL Server 2012 上へ作成しておく必要があります。作成の手順は、次のとおりです。

  1. Management Studio で、次のようにツールバーの[ファイルを開く]ボタンをクリックしま
    す。
    image
    これにより、[ファイルを開く]ダイアログが表示されるので、サンプル スクリプトを解凍し
    たフォルダーを展開して、「NorthwindJ.sql」ファイルを選択し、[開く]ボタンをクリック
    します。
  2. 次のようにデータベースを作成するためのスクリプトが表示されるので、ツールバーの[実行]ボタンをクリックして、スクリプトを実行します。
    image
  3. 数秒後に実行が完了して、次のように画面下に「クエリが正常に実行されました」と表示され
    ることを確認します。
    image
    以上でデータベースの作成が完了です。
    なお、この NorthwindJ データベースは、Microsoft Access 2003 に付属のサンプル データベース「Norhwind」を SQL Server 上へアップサイズしたものを利用していますが、この自習書の手順を試すために、一部のデータを加工しています。
NorthwindJ データベースの構成

NorthwindJ データベースは、Microsoft Access 2003 に付属のサンプル データベース
「Norhwind」を SQL Server 上へアップサイズし、この自習書の手順を試すために、一部のデ
ータを加工したものです。具体的なスキーマ構成は次のとおりです。
image

このデータベースは、商品の販売管理を題材とし、次のように「受注」テーブルと「受注明細」テ
ーブルの中へ受注データが格納されています。

image

「受注」テーブルには、いつ受注したのかや、どの顧客(得意先)からの受注なのかなどの情報が
格納され、「受注明細」テーブルには、各注文の明細(どの商品がいくらで、何個受注したのかな
ど)が格納されています。
また、「受注明細」テーブルの「商品コード」列からは、受注対象となった商品の名前や区分名(商
品分類名)などを「商品」テーブルと「商品区分」テーブルから取得できるようにリレーションシップを設定してあります。

image

「商品」テーブルには、商品データ(ビリビリビールやオタル白ラベルなど)が格納され、「商品
区分」テーブルには、商品分類(飲料や調味料、菓子類など)が格納されています。

3 つ以上のテーブルの結合

3 つ以上のテーブルを結合するには、次のように記述します。

image

INNER JOIN と ON を結合したいテーブルの分だけ記述すれば、複数のテーブルを結合できる
ようになります。

Let's Try
  1. まずは、2 つのテーブルから結合してみましょう。「商品」テーブルと「商品区分」テーブル
    を結合して、次のようなデータになっていることを確認します。
    image
    「商品区分」テーブルには、区分コード「1」の “飲料” や、区分コード「2」の “調味料” などが格納され、「商品」テーブルには、どの区分に属した商品なのかを識別するために「区分コード」列へ値が格納されています。したがって、この 2 つのテーブルを結合するには、次
    のように結合キー列へ「区分コード」を指定します。

    SELECT 区分名, 商品.*
    FROM 商品
    INNER JOIN 商品区分
    ON 商品.区分コード = 商品区分.区分コード


    image
  2. 次に、商品の仕入先が格納されている「仕入先」テーブルとも結合してみましょう。このテー
    ブルのデータは、次のようになっています。
    image
    「仕入先」テーブルとは、「仕入先コード」で結合することができるので、次のように結合キ
    ー列を指定します。

    SELECT 仕入先名, 区分名, 商品.*
    FROM 商品
    INNER JOIN 商品区分
    ON 商品.区分コード = 商品区分.区分コード
    INNER JOIN 仕入先
    ON 商品.仕入先コード = 仕入先.仕入先コード


    image
    「区分名」列の隣へ「仕入先名」列を取得できたことを確認できます。
    このように3 つ以上のテーブルを結合する場合には、INNER JOIN と ON 句をテーブルの分
    だけ追加するようにします。
JOIN でテーブルを記述する順序

複数のテーブルを内部結合する場合、JOIN を記述する順番は関係ありません。

Note: JOIN へ記述したテーブル順に処理させる ~FORCE ORDER~
複数のテーブルを結合する場合の内部的な処理(結合される順番)は、SQL Server が最速だと判断(予測)した順番で行われます。しかし、内部処理を加味するような高度なチューニングでは、その判断を覆したい場合もあります(SQL Server の判断は、あくまでも最速だと予測したものなので、本当に最速だとは限らないのです)。こういった場合、JOIN へ記述したテーブルの順に、SQL Server に処理させることができます。これは SELECT ステートメントの最後に “OPTION (FORCE ORDER)” と指定することで実現できます。Force は「強制」という意味です。
以前に筆者が行った案件では、FORCE ORDER を指定し、テーブルの記述順を変更することで、8 秒かかっていた処理を 3 秒に短縮させたことがあります。このときは、インデックスの作成と結合ヒント(MERGE や LOOP など、結合の内部的な処理方法)の変更も行いましたが、ここまで実行時間を短縮できたのは FORCE ORDER のおかげでした。

Note: クエリ デザイナーで GUI 操作で複数テーブルの結合
前述の Note で説明したように、Management Studio の「クエリ デザイナー」を利用すれば、GUI 操作で複数のテーブルを結合することもできます。「クエリ デザイナー」を起動するには、クエリ エディター上で任意の場所を右クリックして、[エディターでクエリをデザイン]をクリックします。

image

なお、今回の NorthwindJ データベースのように FOREIGN KEY 制約が設定されている場合には、上記の操作で問題ありませんが、もし FOREIGN KEY 制約を設定していない場合は、結合キー列がクエリ デザイナーには分からないので、外部キー列を主キー列へドラッグ&ドロップして、明示的に結合キー(リレーションシップ)を指示する必要があります。

image

このようにドラッグ&ドロップで指示したリレーションシップは、実際に FOREIGN KEY 制約が設定されるわけではありません。FOREIGN KEY 制約は、結合には必須ではないので、ドラッグ&ドロップで行っているのは、あくまでも結合キー列(ON 句)の指示のみです。

受注情報の取得
  1. 次に、受注に関する情報が格納されている「受注」テーブルと「受注明細」テーブルを結合し
    てみましょう。それぞれのテーブルのデータは次のようになっています。
    image
    「受注」テーブルと「受注明細」テーブルを結合するには、次のように「受注コード」列を結
    合キーへ指定します。

    SELECT 受注明細.*, 受注.*
    FROM 受注
    INNER JOIN 受注明細
    ON 受注.受注コード = 受注明細.受注コード


    image
  2. 続いて、商品名が記述されている「商品」テーブルとも結合してみましょう。このテーブルと
    結合するには、「商品コード」列を結合キーへ指定します。

    SELECT 受注明細.*, 商品名, 受注.*
    FROM 受注
    INNER JOIN 受注明細
    ON 受注.受注コード = 受注明細.受注コード
    INNER JOIN 商品
    ON 受注明細.商品コード = 商品.商品コード


    image
    商品テーブルを結合することで、受注明細データを商品名で区別できるようになったことを確認できます。
売上集計

次に、集計関数(SUM や AVG、MAX など)とグループ化を行う GROUP BY 句を使って、
NorthwindJ データベースの売上集計を行ってみましょう。売上データは、前の手順で試したよう
に「受注明細」テーブルへ格納されているので、「単価」(受注時単価)と「数量」を掛け算すれば、
受注金額を計算できるようになります(正確には「割引」列も計算する必要がありますが、ここで
は省略します)。

Let's Try
  1. まずは、"すべての受注金額の合計" を取得してみましょう。

    SELECT SUM(単価 * 数量) FROM 受注明細


    image
    単価と数量を乗算したものに対して SUM 関数で合計を計算し、受注金額の合計を求めています。結果は、2,982 万1,530 円でした。
  2. 次に、GROUP BY 句を利用して、"商品ごとの受注金額の合計" を計算してみましょう。次
    のように記述します。

    SELECT 商品コード, SUM(単価 * 数量) FROM 受注明細
    GROUP BY 商品コード


    image
    商品コード「23」は 8 万400 円、「46」は 12 万5,000 円であったことを確認できます。
  3. 商品コードごとの合計では、どの商品なのかが分かりづらいので、次は、"商品名ごとの受注金額" を取得してみましょう。これを取得するには、次のように「商品」テーブルと結合する
    必要があります。

    SELECT 商品名, SUM(単価 * 数量) FROM 受注明細
    INNER JOIN 商品 ON 受注明細.商品コード = 商品.商品コード
    GROUP BY 商品名


    image
    しかし、結果はエラーになります。「単価」列は、「受注明細」テーブルにも、「商品」テーブ
    ルにも存在するからです。しかし、この2 つの列は、同じ名前の「単価」でも意味が異なりま
    す。「受注明細」テーブルは “受注時” の単価、「商品」テーブルは “標準” の単価です。したがって、受注金額を計算するには、「受注明細」テーブルの「単価」列を利用する必要があります。

    SELECT 商品名, SUM(受注明細.単価 * 数量) FROM 受注明細
    INNER JOIN 商品 ON 受注明細.商品コード = 商品.商品コード
    GROUP BY 商品名


    image
  4. 次に、飲料や調味料、菓子類など、"商品区分名ごとの受注金額" を取得してみましょう。商
    品区分名を取得するには、次のように「商品区分」テーブルを結合します。

    SELECT 区分名, SUM(受注明細.単価 * 数量) FROM 受注明細
    INNER JOIN 商品 ON 受注明細.商品コード = 商品.商品コード
    INNER JOIN 商品区分 ON 商品.区分コード = 商品区分.区分コード
    GROUP BY 区分名


    image
  5. 次に、"受注年ごとの受注金額" を計算してみましょう。受注日(年月日)は、「受注」テーブ
    ルへ格納されていますが、「YEAR」という関数を利用することで、年月日のうちの「年」の
    みを取得できるようになります。

    SELECT YEAR(受注日), SUM(受注明細.単価 * 数量) FROM 受注明細
    INNER JOIN 受注 ON 受注明細.受注コード = 受注.受注コード
    GROUP BY YEAR(受注日)


    image
    2007 年は 868 万2,930 円、2005 年は 1,159 万9,700 円と、年ごとの受注金額の合計を
    取得できたことを確認できます。
  6. 次に、GROUP BY 句へ複数の列を指定して、"受注年ごと、かつ区分名ごとの受注金額" を取得してみましょう。

    SELECT YEAR(受注日), 区分名, SUM(受注明細.単価 * 数量) FROM 受注明細
    INNER JOIN 受注 ON 受注明細.受注コード = 受注.受注コード
    INNER JOIN 商品 ON 受注明細.商品コード = 商品.商品コード
    INNER JOIN 商品区分 ON 商品.区分コード = 商品区分.区分コード
    GROUP BY YEAR(受注日), 区分名
    ORDER BY YEAR(受注日), 区分名


    image
    GROUP BY へ「区分名」列を指定するために、「商品」テーブルと「商品区分」テーブルを
    結合しています。最後の ORDER BY 句は、結果を分かりやすくするために付けています。
    なお、この結果には、全体の合計とそれぞれの列の合計(区分ごとの合計と年ごとの合計)は取得できていません。これを可能にするのが、次に説明する WITH ROLLUP と WITH CUBEです。
WITH ROLLUP と WITH CUBE

前述したように、GROUP BY 句で複数の列を指定した場合には、それらの列を組み合わせたグループ化を行うことはできますが、“全体の合計” と “それぞれの集計結果” を取得することはできません。
これらを取得できるようにするのが「WITH ROLLUP」と「WITH CUBE」です。この2つは、
GROUP BY 句の後へ記述します。

Let's Try: WITH ROLLUP
  1. まずは、「WITH ROLLUP」を利用して、前の Step で取得した "受注年ごと、かつ区分名
    ごとの受注金額" に加えて、"全体の受注金額の合計" と "年ごとの合計" を取得してみまし
    ょう。
    image
    image
    両方の列へ “NULL” と表示される結果が、全体の受注金額合計です。また、「区分名」列が
    “NULL” と表示される結果が、年ごとの受注金額の合計です。このように、WITH ROLLUP
    を利用すると、全体の集計と GROUP BY 句の “1 つ目の列” でグループ化した集計結果を取得できるようになります。
WITH CUBE

WITH ROLLUP は、あくまでも 1 つ目の列の集計結果だけで、2 つ目の列「区分名」でグループ
化した集計結果を取得することができません。これを取得できるようにしたのが「WITH CUBE」
です。では、これを試してみましょう。

  1. 前の手順で記述した SQL の「ROLLUP」の部分を「CUBE」へ置き換えて、実行してみまし
    ょう。
    image
    image

    1 つ目の列に “NULL” と表示され、「区分名」列に “飲料” や “加工食品” と表示されるものが、区分ごとの受注金額の合計です。このように WITH CUBE を利用すると、複数列での集計結果を取得できるようになります。

    Note: CUBE(キューブ)= 立方体
    Cube は「立方体」という意味で、サイコロやルービック キューブの形を思い浮かべると分かりやすいと思います。GROUP BY 句で 2 つの列を指定した集計は、2 次元での集計(クロス集計)、次の図のように 3 つの列を指定(年度と商品区分に加えて、支社ごとの集計も追加)した場合は、キューブの形で表現できるので、WITH CUBE
    というわけです。
    image
    さて、実際の売上分析では、さらに得意先ごとの集計や担当社員ごとの集計を計算したり、3 次元よりも多くの次元(4 次元や5 次元以上)で分析をします。このような分析は、多次元(Multi Dimensional)分析と呼ばれ、専用の製品(OLAP:Online Analytical Processing というカテゴリに分類される製品)が販売されています。OLAP製品を利用すると、独自の多次元データベースを構築して高速にデータ集計を行えるようになります。なお、SQLServer の場合は、無償で同梱される Analysis Services がその機能(OLAP 機能)を持ち、多次元データベースのことを「キューブ」と呼んで管理しています。Analysis Services を利用すると、次のような集計を簡単、かつパフォーマンス良く行えるようになります。
    image
    GROUP BY 句による集計演算は、次元数が多くなればなるほど、指数関数的にパフォーマンスが劣化するので、これを回避するものとして、Analysis Services などの専用の製品が存在しています。本格的な分析を行いたい場合には、Analysis Services の利用を検討することをお勧めします(Analysis Services は、SQL Server に付属の標準機能です)。Analysis Services については、本自習書シリーズの「Analysis Services 入門」編で、基礎からステップ バイ ステップ形式で簡単に試せるように説明していますので、こちらもぜひご覧いただければと思います。

    Note: Oracle での ROLLUP と CUBE
    SWITH ROLLUP と WITH CUBE は、SQL Server 独自の記述方法で、SQL-1999 標準規格(1999 年に規格化された SQL 標準)では次のように記述します(Oracle などでは以下のように記述)。
    GROUP BY ROLLUP( YEAR(受注日), 区分名 )GROUP BY の隣に ROLLUP または CUBE を記述して、グループ化対象の列をカッコで囲みます。

    Note: GROUPING SETS
    SQL Server 2008 からは、WITH CUBE と同じように多次元での集計結果を取得できる関数として GROUPINGSETS が追加されています。これは、SQL-2003 標準規格(2003 年に規格化された SQL 標準)で定義されているもので、Oracle 10g で搭載されている GROUPING SETS とも同じように利用することができます。
    この GROUPING SETS は、GROUP BY 句とともに利用できる集計関数で、複数の集計値を連結(UNION ALL)する場合や、WITH ROLLUP または CUBE を利用して複数項目の集計値を取得する場合の置き換えとして利用することができます。
    たとえば、前述の WITH CUBE で取得した、年ごと・商品区分ごとの合計を取得したものは、次のように記述することができます。
    image
    GROUPGING SETS については、本自習書シリーズの「SQL Server 2008 からの新機能ダイジェスト」編で詳しく説明しています。

クロス集計

WITH ROLLUP と WITH CUBE では、結果が縦に表示されてしまうので、これを次のように 2
次元(クロス集計)の形式でわかりやすく取得することも可能です。
image

Let's Try
  1. 年度を列として表示するには、次のように “CASE 式” を SUM 関数の中で利用します。
    image
    image
    YEAR (受注日) で取得した値を条件に、該当年のみを計算するようにすれば、クロス集計形式で結果を取得できるようになります。
PIVOT によるクロス集計

SQL Server 2005 からは、PIVOT 演算子が追加されて、前の Step のように CASE 式を利用
しなくてもクロス集計結果を取得できるようになりました。これは次のように利用します。

SELECT * FROM
(SELECT 区分名, YEAR(受注日) AS 年
,受注明細.単価 * 数量 AS 受注金額
FROM 受注明細
INNER JOIN 受注 ON 受注明細.受注コード = 受注.受注コード
INNER JOIN 商品 ON 受注明細.商品コード = 商品.商品コード
INNER JOIN 商品区分 ON 商品.区分コード = 商品区分.区分コード
) p
PIVOT ( SUM(受注金額) FOR 年 IN ([2005],[2006],[2007]) ) AS pvt
ORDER BY 区分名

image

サブクエリとして集計対象となるデータを取得し、それに対して PIVOT 演算子で SUM 関数で
処理しています。「FOR ~ IN」の部分で列として表示したい値を列挙します。

ビュー: CREATE VIEW

SELECT ステートメントで結合するテーブルが増えてくると、記述が複雑になってきます。このよ
うな場合に、SELECT ステートメントを 1 つのパッケージとして保存できる機能があります。そ
れが「ビュー」(View)機能です。ビューを作成するには、CREATE VIEW ステートメントを利
用します。構文は、次のとおりです。

image

Let's Try
  1. まずは、「受注」と「受注明細」、「商品」、「商品区分」テーブルを結合する SELECT ステー
    トメントに対して、「受注商品一覧」という名前のビューを作成してみましょう。
    image
    結果はエラーになります。ビューを作成する場合は、SELECT で取得する列に同じ名前の列が存在しているとエラーになります(上の例では「*」ですべての列を取得しています)。したがって、次のように特定の列のみを取得するように変更しなければなりません。
    image
  2. 作成したビューは、次のようにオブジェクト エクスプローラーの[ビュー]フォルダーを展
    開すると確認することができます。
    image

    Note: バッチの先頭ではない場合のエラー
    CREATE VIEW ステートメントは、バッチの先頭で実行しないと、次のエラーが発生します。
    image
    バッチの区切りは、「go」コマンドで行えるので、CREATE VIEW ステートメントを実行する上へ「go」を追加すれば、このエラーを回避することができます。
    image

     

     

ビューの参照
  1. 作成したビューを参照するには、テーブルを利用する場合と同じように SELECT ステートメ
    ントの FROM 句で指定します。image
    これにより、ビューの中で定義した SELECT ステートメントが実行されて、4 つのテーブル
    を JOIN した結果を取得できたことを確認できます。
  2. 次に、GROUP BY 句を利用して、"区分ごとの受注金額の合計" を取得してみましょう。
    image
    わずか 2 行のステートメントだけで、区分ごとに受注金額の合計を取得できたことを確認で
    きます。このように、ビューを利用すれば、複雑な JOIN を記述することなく、複数のテー
    ブルをまたがったデータ取得を簡単に行えるようになります。なお、ビューは、テーブルと同
    じように利用できるので “仮想表” とも呼ばれています。

    Note: ACCESS のクエリ機能に相当
    ビューは、Access の「クエリ」機能に相当します。ただし、Access のクエリとまったく同じというわけではありません。Access のクエリには、“パラメーター化” を行う機能がありますが、ビューにはないからです。SQL Serverでパラメーター化クエリを作成したい場合は、「ストアド プロシージャ」機能を利用する必要があります。ストアド プロシージャについては、本自習書シリーズの「開発者のための Transact-SQL 応用」編で詳しく説明していますので、こちらもぜひご覧いただければと思います。

    Note: Management Studio でのビューの作成: ビュー デザイナー
    Management Studio の「ビュー デザイナー」機能を利用すると、Access でクエリを作成するのと同じような感覚で、GUI 操作でビューを作成することができます。これは、次のように操作します。
    image

    Note: ビュー経由の更新
    ビューに対して、UPDATE や INSERT、DELETE など、更新系のステートメントを実行することも可能です。ただし、ビュー内で GROUP BY や集計関数、DISTINCT 処理を行っていたり、演算結果を行っている列に対しては、更新系のステートメントを実行することはできません。なお、このような場合に「INSTEAD OF トリガー」と呼ばれるトリガーを作成すると、ビューに対して更新系のステートメントが実行されたときに、別の処理を記述できるようになります(ビューのもとになっているテーブルを直接更新するようなステートメントを記述できるよ
    うになります)。

2013年4月5日金曜日

◆アプリケーションからの利用

この Step で作成するアプリケーション

Windows アプリケーション
image

ASP.NET アプリケーション
image

ReportViewer コントロールからのアクセス
ReportViewer コントロールからのアクセス

Windows フォームや Web フォームなどのアプリケーションから、レポートへアクセスするには、ReportViewer コントロールを利用します。
image

それでは、実際に SalesRepo レポートへアクセスする Windows アプリケーションを作成してみましょう。ここでは、Visual Studio 2010 を例に説明します。

  1. まずは、Visual Stduio 2010 を起動して、[ファイル]メニューから[新規作成]→[プロジェクト]をクリックします。
  2. [新しいプロジェクト]ダイアログが表示されたら、[インストールされたテンプレート]から今回は「Visual Basic」を選択して、「Windows フォーム アプリケーション」を選択します。
    image
    [名前]と[場所]へ任意のプロジェクト名と保存場所を入力して、[OK]ボタンをクリックします。
  3. 次に、ツールボックスの[レポート]カテゴリから、[ReportViewer]コントロールを Windows フォーム上へドラッグ&ドロップします。
    image
  4. 配置後、ReportViewer コントロールの右上に出ている「」をクリックします。
    image
    これにより、[ReportViewer タスク]スマート タグが表示されるので、[レポートの選択]で「サーバー レポート」を選択します。[レポート サーバーの URL]は、「http://localhost/reportserver」と設定されていることを確認し(必要に応じてサーバー名を変更し)、[レポート パス]へレポートのパス(今回は /SalesRepo)を入力します。
  5. 次に、ReportViewer コントロールの大きさを調整して、レポートを表示しやすくしてから、ツールバーの[デバッグ開始]ボタンをクリックします。
    image
  6. これにより、Windows アプリケーションが起動して、レポートが表示されることを確認できます。
    image
    任意の商品区分を選択して、[レポートの表示]ボタンをクリックすると、選択した商品区分のみが表示されることを確認できます。
    このように、ReportViewer コントロールを利用すると、アプリケーションから簡単にレポートへアクセスできるようになります。
ファイルへのエクスポート

次に、起動した Windows アプリケーションから、ファイルのエクスポートをしてみましょう。

  1. 次のように[エクスポート]ボタンをクリックして、今回は「Excel」をクリックします。
    image
  2. [名前を付けて保存]ダイアログが表示されたら、[ファイル名]へ任意の名前を入力して、[保存]ボタンをクリックします。
  3. 保存した Excel ファイルを開きます。
    image
    このように、Windows アプリケーションからでも、ファイルへのエクスポートを簡単に行うことができます。
エクスポート ボタンの非表示

ReportViewer コントロールでは、プロパティを設定して、レポート ツールバーをカスタマイズすることもできます。それではこれを試してみましょう。

  1. 配置した ReportViewer コントロールをクリックして、ReportViewer コントロールの[プロパティ]を表示します。
    image
    プロパティの一覧から、[ツール バー]セクションにある[ShowExportButton]を「False」へ設定します。これで、エクスポート ボタンを表示しないようにすることができます。
  2. [デバッグ開始]ボタンをクリックして、結果を確認してみましょう。
    image
    このように、ReportViewer コントロールの[ツールバー]セクションにあるプロパティを利用すれば、レポート ツールバーにあるボタンの表示/非表示を設定することができます。
パラメーターの指定
パラメーターの指定

ReportViewer コントロールで、パラメーターを指定するには、Microsoft.Reporting.Win Forms 名前空間の ReportParameter クラスを利用します。

  1. Windows フォームをダブル クリックして、Form_load イベント ハンドラーを生成し、次のようにコードを記述します。
    image
  2. [デバッグ開始]ボタンをクリックして、結果を確認します。
    image
    p1 パラメーター(商品区分コード)が 3の菓子類のデータが表示されることを確認できます。
    このように、ReportParameter オブジェクトを利用すると、プログラム内からレポートのパラメーターを指定することができます。

    Note: 複数選択可能なパラメーターがある場合
    「年」パラメーター(p2)のように、複数選択可能なパラメーターがある場合は、次のように配列として、値を代入する必要があります。
    image
    (C#)
    image

ASP.NET Web フォームからのアクセス

ASP.NET Web フォームからレポートへアクセスする場合にも、Windows フォームの場合と同じように ReportViewer コントロールを利用します(利用方法についても、Windows フォームの場合とまったく同じです)。

試してみたが、私の環境ではスクリプトエラーが発生し動作しなかった。(VS2012)
  JavaScriptのバージョンを選んだりするのかしらん?

その後、もう少し試してみました。
エラーが発生するのは、自習書99ページのカスケードパラメータを使った場合。
商品区分を選ぶと、その商品区分の商品だけがコンボボックスに表示されるパターン。
この時、商品コンボボックスを表示するとエラーとなる。
情けないことに、これ、IEのバグの様です。(IE9以降で発生)
他のブラウザ(FireFox,Chrome,Opera)では発生しません。
image

とりあえず以下のようなスクリプトを追加してエラー発生時に「getComputedStyle」関数を置き換えることで回避できるようです。

<script type="text/javascript">

    if (window.getComputedStyle != null) {

        var orginalGetComputedStyle = window.getComputedStyle;

        window.getComputedStyle = function (element, parm) {

            try {

                return orginalGetComputedStyle(element, null);

            }

            catch (err) {

                return orginalGetComputedStyle(

                    document.getElementsByTagName("body")[0], null);

            }

        }

    }

</script>

この様な不具合がIE9からそのままという事は、この機能もほとんど使われていないのでしょうね・・・。

  1. Visual Stduio 2010 を起動し、[ファイル]メニューから[新規作成]→[プロジェクト]をクリックします。
    image
  2. [新しいプロジェクト]ダイアログが表示されたら、[インストールされたテンプレート]から「Visual Basic」を選択して、「ASP.NET Web アプリケーション」を選択します。
    image
  3. 次に、[デザイン]タブをクリックしてデザイン画面を表示して、ツールボックスの[AJAX Extensions]カテゴリから、[ScriptManager]を Web フォーム上へドラッグ&ドロップします。
    image

    Note: Visual Studio 2010 では、ReportViewer が AJAX 対応のコントロール
    Visual Studio 2010 からは、ReportViewer コントロールが AJAX 対応のコントロールに変更されました。このため、ScriptManager コントロールの配置が必要になります。

  4. 次に、ツールボックスの[レポート]カテゴリから[ReportViewer]コントロールを Web フォーム上へドラッグ&ドロップします。
    image
  5. [ReportViewer タスク]スマート タグが表示されたら、[レポートの選択]で「サーバー レポート」を選択し、[レポート サーバーの URL]へは、「http://localhost/reportserver」と設定されていることを確認します。[レポート パス]へは、レポートのパス(今回は /SalesRepo)を入力します。
    image
  6. ツール バーの[デバッグ開始]ボタンをクリックして、実行します。
    image
    レポートが表示されたら、任意の商品区分名を選択して、[レポートの表示]ボタンをクリックし、選択した商品区分のデータが、正しく表示されることを確認します。
    このように、ASP.NET Web アプリケーションでも、Windows アプリケーションと同様に ReportViewer コントロールを利用して、簡単にレポートへアクセスすることができます。