QA@IT
«質問へ戻る

敬称抜け修正

4
本文
 ```
 共通テーブル式を使用する方法がもっとも速いようです。また、distinctは遅く、countを取得するよりも時間がかかるようです。実行計画を見ても、90%以上の時間がdistinctするために費やされていました。
 性能では、Oakbow7さんの、簡潔さと性能のバランスでは、jijiさんの方法が良いようです。
-Oakbow7の記述でも、組み合わせによってパターンが爆発することはないため、Oakbow7さんの方法をacceptします。
+Oakbow7さんの記述でも、組み合わせによってパターンが爆発することはないため、Oakbow7さんの方法をacceptします。

レコードを参照するレコードの有無だけを高速に取得したい

SQL Server 2005を使用しています。
以下のようなテーブルがあるとします。
テーブル A
id (int型)
テーブル B
id (int型)
a_id (int型)

この時、Aのレコードごとに、テーブルBにあるa_idが、idと一致するレコードの有無を取得するには、

select
 A.id,
 count(B.id) as B_count
from
 A
left outer join
 B
on
 B.a_id = A.id
group by
 A.id

を実行して、B_countが1以上であれば、該当するレコードがあると判定できます。
しかし、欲しい情報は、0か、1以上かのいずれかであるため、countは欲しい情報に対して過剰です。
そこで、以下のように記述したところ、テーブルBにレコードが50万ほどある状態で、実行時間が4倍ほど高速になりました。

select
 A.id,
 0 as B_exists
from
 A
where
 not exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )
union
select
 A.id,
 1 as B_exists
from
 A
where
 exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )

外部キー経由で参照するテーブルが1個の場合は、これで良いのですが、参照するテーブルの個数が1つ増えるごとに、unionで結合するselect文の個数が2倍に増加します。
この文と同等の結果を、同等以下の時間で得られる文を、SQL標準に則ったものか、SQL Server固有の方法か、いずれかの方法で、より簡潔に記述する方法はないでしょうか?

追記
実際のデータ量に近づけて、各SQL文の実行計画を取得しました。データ量は、Aが80レコード、Bが約50万レコードです。また、実際には、各テーブルに関係ないカラムが存在しますが、実行計画を見たところ、ほとんど影響はありませんでした。
B.a_idには、インデックスを追加してあります。
速い順に並べた結果は、以下のようになりました。

Oakbow7         0.0267094
yasuyuki        0.0301459
jiji            0.0467235
flied_onion     0.490731
alice-asahina   0.490798

共通テーブル式を使用する方法がもっとも速いようです。また、distinctは遅く、countを取得するよりも時間がかかるようです。実行計画を見ても、90%以上の時間がdistinctするために費やされていました。
性能では、Oakbow7さんの、簡潔さと性能のバランスでは、jijiさんの方法が良いようです。
Oakbow7さんの記述でも、組み合わせによってパターンが爆発することはないため、Oakbow7さんの方法をacceptします。

SQL Server 2005を使用しています。
以下のようなテーブルがあるとします。
テーブル A
id (int型)
テーブル B
id (int型)
a_id (int型)

この時、Aのレコードごとに、テーブルBにあるa_idが、idと一致するレコードの有無を取得するには、
```
select
 A.id,
 count(B.id) as B_count
from
 A
left outer join
 B
on
 B.a_id = A.id
group by
 A.id
```
を実行して、B_countが1以上であれば、該当するレコードがあると判定できます。
しかし、欲しい情報は、0か、1以上かのいずれかであるため、countは欲しい情報に対して過剰です。
そこで、以下のように記述したところ、テーブルBにレコードが50万ほどある状態で、実行時間が4倍ほど高速になりました。
```
select
 A.id,
 0 as B_exists
from
 A
where
 not exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )
union
select
 A.id,
 1 as B_exists
from
 A
where
 exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )
```
外部キー経由で参照するテーブルが1個の場合は、これで良いのですが、参照するテーブルの個数が1つ増えるごとに、unionで結合するselect文の個数が2倍に増加します。
この文と同等の結果を、同等以下の時間で得られる文を、SQL標準に則ったものか、SQL Server固有の方法か、いずれかの方法で、より簡潔に記述する方法はないでしょうか?

追記
実際のデータ量に近づけて、各SQL文の実行計画を取得しました。データ量は、Aが80レコード、Bが約50万レコードです。また、実際には、各テーブルに関係ないカラムが存在しますが、実行計画を見たところ、ほとんど影響はありませんでした。
B.a_idには、インデックスを追加してあります。
速い順に並べた結果は、以下のようになりました。
```
Oakbow7			0.0267094
yasuyuki		0.0301459
jiji			0.0467235
flied_onion		0.490731
alice-asahina	0.490798
```
共通テーブル式を使用する方法がもっとも速いようです。また、distinctは遅く、countを取得するよりも時間がかかるようです。実行計画を見ても、90%以上の時間がdistinctするために費やされていました。
性能では、Oakbow7さんの、簡潔さと性能のバランスでは、jijiさんの方法が良いようです。
Oakbow7さんの記述でも、組み合わせによってパターンが爆発することはないため、Oakbow7さんの方法をacceptします。

実行計画を取得した結果を追記

4
本文
 ```
 外部キー経由で参照するテーブルが1個の場合は、これで良いのですが、参照するテーブルの個数が1つ増えるごとに、unionで結合するselect文の個数が2倍に増加します。
 この文と同等の結果を、同等以下の時間で得られる文を、SQL標準に則ったものか、SQL Server固有の方法か、いずれかの方法で、より簡潔に記述する方法はないでしょうか?
+
+追記
+実際のデータ量に近づけて、各SQL文の実行計画を取得しました。データ量は、Aが80レコード、Bが約50万レコードです。また、実際には、各テーブルに関係ないカラムが存在しますが、実行計画を見たところ、ほとんど影響はありませんでした。
+B.a_idには、インデックスを追加してあります。
+速い順に並べた結果は、以下のようになりました。
+```
+Oakbow7			0.0267094
+yasuyuki		0.0301459
+jiji			0.0467235
+flied_onion		0.490731
+alice-asahina	0.490798
+```
+共通テーブル式を使用する方法がもっとも速いようです。また、distinctは遅く、countを取得するよりも時間がかかるようです。実行計画を見ても、90%以上の時間がdistinctするために費やされていました。
+性能では、Oakbow7さんの、簡潔さと性能のバランスでは、jijiさんの方法が良いようです。
+Oakbow7の記述でも、組み合わせによってパターンが爆発することはないため、Oakbow7さんの方法をacceptします。

レコードを参照するレコードの有無だけを高速に取得したい

SQL Server 2005を使用しています。
以下のようなテーブルがあるとします。
テーブル A
id (int型)
テーブル B
id (int型)
a_id (int型)

この時、Aのレコードごとに、テーブルBにあるa_idが、idと一致するレコードの有無を取得するには、

select
 A.id,
 count(B.id) as B_count
from
 A
left outer join
 B
on
 B.a_id = A.id
group by
 A.id

を実行して、B_countが1以上であれば、該当するレコードがあると判定できます。
しかし、欲しい情報は、0か、1以上かのいずれかであるため、countは欲しい情報に対して過剰です。
そこで、以下のように記述したところ、テーブルBにレコードが50万ほどある状態で、実行時間が4倍ほど高速になりました。

select
 A.id,
 0 as B_exists
from
 A
where
 not exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )
union
select
 A.id,
 1 as B_exists
from
 A
where
 exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )

外部キー経由で参照するテーブルが1個の場合は、これで良いのですが、参照するテーブルの個数が1つ増えるごとに、unionで結合するselect文の個数が2倍に増加します。
この文と同等の結果を、同等以下の時間で得られる文を、SQL標準に則ったものか、SQL Server固有の方法か、いずれかの方法で、より簡潔に記述する方法はないでしょうか?

追記
実際のデータ量に近づけて、各SQL文の実行計画を取得しました。データ量は、Aが80レコード、Bが約50万レコードです。また、実際には、各テーブルに関係ないカラムが存在しますが、実行計画を見たところ、ほとんど影響はありませんでした。
B.a_idには、インデックスを追加してあります。
速い順に並べた結果は、以下のようになりました。

Oakbow7         0.0267094
yasuyuki        0.0301459
jiji            0.0467235
flied_onion     0.490731
alice-asahina   0.490798

共通テーブル式を使用する方法がもっとも速いようです。また、distinctは遅く、countを取得するよりも時間がかかるようです。実行計画を見ても、90%以上の時間がdistinctするために費やされていました。
性能では、Oakbow7さんの、簡潔さと性能のバランスでは、jijiさんの方法が良いようです。
Oakbow7の記述でも、組み合わせによってパターンが爆発することはないため、Oakbow7さんの方法をacceptします。

SQL Server 2005を使用しています。
以下のようなテーブルがあるとします。
テーブル A
id (int型)
テーブル B
id (int型)
a_id (int型)

この時、Aのレコードごとに、テーブルBにあるa_idが、idと一致するレコードの有無を取得するには、
```
select
 A.id,
 count(B.id) as B_count
from
 A
left outer join
 B
on
 B.a_id = A.id
group by
 A.id
```
を実行して、B_countが1以上であれば、該当するレコードがあると判定できます。
しかし、欲しい情報は、0か、1以上かのいずれかであるため、countは欲しい情報に対して過剰です。
そこで、以下のように記述したところ、テーブルBにレコードが50万ほどある状態で、実行時間が4倍ほど高速になりました。
```
select
 A.id,
 0 as B_exists
from
 A
where
 not exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )
union
select
 A.id,
 1 as B_exists
from
 A
where
 exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )
```
外部キー経由で参照するテーブルが1個の場合は、これで良いのですが、参照するテーブルの個数が1つ増えるごとに、unionで結合するselect文の個数が2倍に増加します。
この文と同等の結果を、同等以下の時間で得られる文を、SQL標準に則ったものか、SQL Server固有の方法か、いずれかの方法で、より簡潔に記述する方法はないでしょうか?

追記
実際のデータ量に近づけて、各SQL文の実行計画を取得しました。データ量は、Aが80レコード、Bが約50万レコードです。また、実際には、各テーブルに関係ないカラムが存在しますが、実行計画を見たところ、ほとんど影響はありませんでした。
B.a_idには、インデックスを追加してあります。
速い順に並べた結果は、以下のようになりました。
```
Oakbow7			0.0267094
yasuyuki		0.0301459
jiji			0.0467235
flied_onion		0.490731
alice-asahina	0.490798
```
共通テーブル式を使用する方法がもっとも速いようです。また、distinctは遅く、countを取得するよりも時間がかかるようです。実行計画を見ても、90%以上の時間がdistinctするために費やされていました。
性能では、Oakbow7さんの、簡潔さと性能のバランスでは、jijiさんの方法が良いようです。
Oakbow7の記述でも、組み合わせによってパターンが爆発することはないため、Oakbow7さんの方法をacceptします。

質問を投稿

レコードを参照するレコードの有無だけを高速に取得したい

SQL Server 2005を使用しています。
以下のようなテーブルがあるとします。
テーブル A
id (int型)
テーブル B
id (int型)
a_id (int型)

この時、Aのレコードごとに、テーブルBにあるa_idが、idと一致するレコードの有無を取得するには、

select
 A.id,
 count(B.id) as B_count
from
 A
left outer join
 B
on
 B.a_id = A.id
group by
 A.id

を実行して、B_countが1以上であれば、該当するレコードがあると判定できます。
しかし、欲しい情報は、0か、1以上かのいずれかであるため、countは欲しい情報に対して過剰です。
そこで、以下のように記述したところ、テーブルBにレコードが50万ほどある状態で、実行時間が4倍ほど高速になりました。

select
 A.id,
 0 as B_exists
from
 A
where
 not exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )
union
select
 A.id,
 1 as B_exists
from
 A
where
 exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )

外部キー経由で参照するテーブルが1個の場合は、これで良いのですが、参照するテーブルの個数が1つ増えるごとに、unionで結合するselect文の個数が2倍に増加します。
この文と同等の結果を、同等以下の時間で得られる文を、SQL標準に則ったものか、SQL Server固有の方法か、いずれかの方法で、より簡潔に記述する方法はないでしょうか?

SQL Server 2005を使用しています。
以下のようなテーブルがあるとします。
テーブル A
id (int型)
テーブル B
id (int型)
a_id (int型)

この時、Aのレコードごとに、テーブルBにあるa_idが、idと一致するレコードの有無を取得するには、
```
select
 A.id,
 count(B.id) as B_count
from
 A
left outer join
 B
on
 B.a_id = A.id
group by
 A.id
```
を実行して、B_countが1以上であれば、該当するレコードがあると判定できます。
しかし、欲しい情報は、0か、1以上かのいずれかであるため、countは欲しい情報に対して過剰です。
そこで、以下のように記述したところ、テーブルBにレコードが50万ほどある状態で、実行時間が4倍ほど高速になりました。
```
select
 A.id,
 0 as B_exists
from
 A
where
 not exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )
union
select
 A.id,
 1 as B_exists
from
 A
where
 exists (
  select
   *
  from
   B
  where
   B.a_id = A.id
 )
```
外部キー経由で参照するテーブルが1個の場合は、これで良いのですが、参照するテーブルの個数が1つ増えるごとに、unionで結合するselect文の個数が2倍に増加します。
この文と同等の結果を、同等以下の時間で得られる文を、SQL標準に則ったものか、SQL Server固有の方法か、いずれかの方法で、より簡潔に記述する方法はないでしょうか?