2011-01-14 15 views
19

「With Clause」を使用するサンプルSQLサーバースクリプトを表示できますか?「With Clause」SQL Server 2008

私は、この句を使用して、クエリを実行しようとしているのと同じテーブルを含む200個のデータベースを反復しようとしています。私はカーソルを使用しないようにしようとしています。なぜなら、クエリーの時間が長くなり、whileループを使用するためです。

私ができることについて誰かに助言することはできますか?

ありがとうございます。

+1

「WITH」はこのタスクでは役に立ちません。すべてのデータベースは同じインスタンスにありますか?それらのすべてで実行しているコードは何ですか? –

+3

[プリンセス・ブライド](http://www.imdb.com/title/tt0093779/)のInigo Montoyaの言葉を引用すると:「あなたはその言葉を使い続けています。 :-) –

+1

Martin、はい、同じインスタンスにあります。各データベースには同じテーブルがあります。 sum関数を使用してテーブルからすべてのデータを収集し、各データベースの名前をDBNAME、IMG_COUNT、DATEという列の一時テーブルに格納します。テーブルの名前はtbldocまたはdbo.tbldocです。各データベースにはこのテーブルが含まれており、すべてのクエリに同じ列があります。カーソルやwhileループを使用するのではなく、これを高速化するのに何が必要でしょうか? – Jeff

答えて

31

WITHだけで突くを使用してSELECT文ですが、ここではFizzBu​​zz :) 100行を記述するための別の方法です私は数える、WITHステートメントを示すために十分です。

;WITH t100 AS (
SELECT n=number 
FROM master..spt_values 
WHERE type='P' and number between 1 and 100 
)     
SELECT 
    ISNULL(NULLIF(
    CASE WHEN n % 3 = 0 THEN 'Fizz' Else '' END + 
    CASE WHEN n % 5 = 0 THEN 'Buzz' Else '' END, ''), RIGHT(n,3)) 
FROM t100 

しかし、SQL Server 2005で(共通テーブル式http://msdn.microsoft.com/en-us/library/ms190766.aspx「CTE」として知られている)での背後にある本当のパワーと上記再帰で、テーブルは、仮想テーブルへの追加の反復によって構築された場合、以下のように毎回。

;WITH t100 AS (
SELECT n=1 
union all 
SELECT n+1 
FROM t100 
WHERE n < 100 
)     
SELECT 
    ISNULL(NULLIF(
    CASE WHEN n % 3 = 0 THEN 'Fizz' Else '' END + 
    CASE WHEN n % 5 = 0 THEN 'Buzz' Else '' END, ''), RIGHT(n,3)) 
FROM t100 

は、すべてのデータベースで同様のクエリを実行するには、文書化されていない sp_msforeachdbを使用することができます。別の答えで言及されていますが、sp_foreachdbではなくsp_msforeachdbです。

ご使用の際には注意が必要です。予想外のこともありますので、ご注意ください。この例を検討してください

exec sp_msforeachdb 'select count(*) from sys.objects' 

各DB内のオブジェクト数ではなく、SAMEカウントが報告され、現在のDBから開始されます。 これを回避するには、まずデータベースを常に使用してください。角カッコは、複数語のデータベース名を修飾するために注意してください。集計表の移入についてのあなたの特定のクエリのために

exec sp_msforeachdb 'use [?]; select count(*) from sys.objects' 

、あなたは以下のようなものを使用することができます。 DATE列についてはわからないので、この集計表にはDBNAME列とIMG_COUNT列のみがありますが、それが役立つことを願っています。

create table #tbl (dbname sysname, img_count int); 

exec sp_msforeachdb ' 
use [?]; 
if object_id(''tbldoc'') is not null 
insert #tbl 
select ''?'', count(*) from tbldoc' 

select * from #tbl 
+1

よ、私はこれを行うための最善の方法のように見えるwhileループと比較して処理が速いwhileループを使用するようだ。これは私がこれまで持っていたものです – Jeff

+0

これは本当に私がページングボタンクリックグリッドのデータを得るのを手伝ってくれました。どうもありがとう。 –

1

sp_foreachdbプロシージャを実行してください。

+0

これはカーソルを使うだけなので、OPの現在のシステムでは劇的なスピードのパフォーマンスにはならないでしょう(これは可能であるとは思えません) –

+0

Martin、はい、同じインスタンスにあります。各データベースには同じテーブルがあります。特定の列に対してsum関数を使用して、表からすべてのデータを収集し、各データベースの名前をDBNAME、IMG_COUNT、DATEという列の一時表に移入したいとします。テーブルの名前はtbldocまたはdbo.tbldocです。各データベースにはこのテーブルが含まれており、すべてのクエリに同じ列があります。カーソルやwhileループを使用するのではなく、これを高速化するのに何が必要でしょうか? – Jeff

+0

ルーピングなしでこれを行う方法はありません。しかし、大部分の時間は、ループ自体ではなく個々のクエリに取り込まれます。あなたは(1)それを少し試して並列化することができます。 (2)すべてのデータベースの 'tbldoc'が、実行されているクエリのための適切なインデックスを持っていることを確認するか、(3)いくつかの事前計算を試してみてください。 –

7

WITH句の2つのタイプがあります。

はここでは、共通テーブル式(CTE)で使用して、SQL形式でFizzBu​​zzです。ここで

;WITH mil AS (
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY c.column_id) [n] 
FROM master.sys.all_columns as c 
CROSS JOIN master.sys.all_columns as c2 
)     
SELECT CASE WHEN n % 3 = 0 THEN 
      CASE WHEN n % 5 = 0 THEN 'FizzBuzz' ELSE 'Fizz' END 
     WHEN n % 5 = 0 THEN 'Buzz' 
     ELSE CAST(n AS char(6)) 
    END + CHAR(13) 
FROM mil 

も句

SELECT * FROM orders WITH (NOLOCK) where order_id = 123 
+0

ありがとう、その有用な –