河端善博 ブログ / SQL Server / PASSJ

SQL Server, .NET, PASSJ

  PASSJブログ :: ホーム :: 連絡をする :: RSS  :: ATOM :: Login
  952 投稿数 :: 112 ストーリー :: 1482 コメント :: 597 トラックバック

ニュース

Windows Live Alerts
My Yahoo!に追加
Add to Google dotnetnuke.jp
NPOPLUS.JP
MVP
PASSJ

記事のカテゴリ

過去の記事

カテゴリ

イメージギャラリ

.TEXT

INETA コミュニティ

MOM2005

MSMVP

PASSJ

SQL コミュニティ

セキュリティ TIPS

セキュリティのキホン

テスト

ブログ翻訳

多言語対応

.TEXT

INETA コミュニティ

MOM2005

MSMVP

PASSJ

SQL コミュニティ

セキュリティ TIPS

セキュリティのキホン

テスト

ブログ翻訳

多言語対応

ちょっとしたクエリーの紹介です。

■シナリオ
ふたつのSELECT の結果を UNION ALL で結合する。
その結果を ORDER BY で並べ替えて、TOP 5 で先頭から 5つだけ抽出したい

■サンプル

USE [pubs]
 
SELECT TOP 5 *
FROM 
(
  SELECT * FROM authors WHERE state = 'CA'
  UNION ALL
  SELECT * FROM authors WHERE state = 'KS'
) AS U
ORDER BY au_lname

■ポイント
サブクエリーを利用します。
UNION ALL の結果を ( ... ) AS U として、FROM に指定します。
U は、UNION ALL の結果に、名前をつけています。

投稿日時 : 2004年3月9日 10:03

コメントを追加

# re: ふたつの SELECT の結果を UNION ALL して、ORDER BY して、TOP 5 したい 2004/03/09 11:13 おがわみつぎ
Orber By を指定していることもポイントですね。

# re: ふたつの SELECT の結果を UNION ALL して、ORDER BY して、TOP 5 したい 2004/03/09 22:29 渋谷 泰宏
サブクエリにも ORDER と TOP つけた方が速いかも。

# re: ふたつの SELECT の結果を UNION ALL して、ORDER BY して、TOP 5 したい 2004/03/10 11:46 渋谷 泰宏
> サブクエリにも ORDER と TOP つけた方が速いかも。

少し試してみました。(サブクエリのサブクエリにて)
ほとんどの場合で同等あるいは遅くなってしまいました。

単純に考えてデータ量を減らしてから UNION した方が
速いように思ったのですが。。
UNION 恐るべし。いや、オプティマイザ恐るべしですか。

サブクエリの各 SELECT が別のサーバーのテーブルを
参照するような場合は試せてないです。


もう一つ面白かったのは、サンプルのように同じテーブルに
対して違う WHERE 条件で結果を抽出したい場合、
UNION を使わずに WHERE 句に OR を使ってしまうよりも
UNION を使って WHERE 句から OR を除去した方が
速いことが多いということです。

今までクエリのチューニングで UNION を使用することは、
考えもしていませんでしたが、ありなのかもしれません。

UNION の可能性を感じました。

# re: ふたつの SELECT の結果を UNION ALL して、ORDER BY して、TOP 5 したい 2004/03/10 13:27 河端善博
サンプルでは、同じテーブルで条件だけ変更して UNION しています。
これは、単純にサンプルとしての、「わかりやすさ」のみでした。
しかし、渋谷さんの解析されたように、ORよりも UNION ALL が早くなる場合が多いですね。
このことは、PASSJ Conference 2001で、キンバリーさんが発表されて、会場が驚いていました。
いま、思い出した次第です

# re: ふたつの SELECT の結果を UNION ALL して、ORDER BY して、TOP 5 したい 2004/03/12 13:16 CAMUS
UNION ALL じゃないとダメですか?
今回の内容だと、UNIONでも同じ結果になると思いますが、同じテーブルをスキャンするのであれば、

select top 5 * from authors a
where Exists
(select 't'
from authors a1
where a.au_id = a1.au_id and
exists (select *
from (select 'CA' states
union
select 'KS' states) t
where t.states = a1.state))
order by au_lname

なんて書き方もできます。
テーブルスキャンの回数がUNIONを使うよりも減ることが大きなポイントです。
複雑ではありますが、コストがだいぶ変わるので、ご参考までに…。

# re: ふたつの SELECT の結果を UNION ALL して、ORDER BY して、TOP 5 したい 2004/03/12 13:37 河端善博
ありがとうございます。
もう一度、検証してみたいと思います。
from
(
SELECT 'CA' states
UNION
SELECT 'KS' states
) t
の部分が面白い。
TIPS としてまとめたいな。

# re: ふたつの SELECT の結果を UNION ALL して、ORDER BY して、TOP 5 したい 2004/03/12 14:58 CAMUS
あ゛ー…すみません。

select top 5 * from authors a
where exists (select *
from (select 'CA' states
union
select 'KS' states) t
where t.states = a.state)
order by au_lname

でした。(_o_)
先に書いたのは冗長すぎます。失礼しました。(_o_)

コメント

タイトル:
名前:
Url:
コメント: