質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

2回答

5832閲覧

SQLの結果が返ってくるのに時間がかかりすぎる

退会済みユーザー

退会済みユーザー

総合スコア0

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2019/04/24 04:00

イメージ説明

画像のようなレコードのテーブルがあります。
<organNum>は組織コードとして11,31,51の3パターンがあります。
<dtDateTime>は記録された時間になります。
<timeUnit><dtDateTime>をHHで区別した値になります。
<timeGroup>は午前=10, 午後=20くらいのものだと思ってください。(今回の質問には関係ないため)

これに対してのSELECT文が

SQL

1SELECT 2 organNum, 3 timeUnit, 4 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 4 THEN 1 ELSE 0 END) AS '4月', 5 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 5 THEN 1 ELSE 0 END) AS '5月', 6 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 6 THEN 1 ELSE 0 END) AS '6月', 7 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 7 THEN 1 ELSE 0 END) AS '7月', 8 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 8 THEN 1 ELSE 0 END) AS '8月', 9 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 9 THEN 1 ELSE 0 END) AS '9月', 10 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 10 THEN 1 ELSE 0 END) AS '10月', 11 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 11 THEN 1 ELSE 0 END) AS '11月', 12 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 12 THEN 1 ELSE 0 END) AS '12月', 13 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 1 THEN 1 ELSE 0 END) AS '1月', 14 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 2 THEN 1 ELSE 0 END) AS '2月', 15 SUM(CASE WHEN DATEPART(MONTH,dtDateTime) = 3 THEN 1 ELSE 0 END) AS '3月', 16FROM 17 テーブル 18GROUP BY 19 organNum, timeUnit 20

というように月ごとにカウントをとり、organNumとtimeUnitでグループ化をしています。
自分では問題のないSQLだと思うのですが、これの結果が返ってくるのに6分もかかってしまいます。
レコードが多すぎるのではないかと思いましたが、4600件ほどしか入っておらず、問題になっているとは思えません。
また、予定ですが7~8万件のレコードが入る予定です。

何かパフォーマンスを著しく下げる要因があれば教えて頂きたいです。よろしくお願いします。
環境はSQLServer2016です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2019/04/24 06:42

多分インデックスでしょうね。実行計画があれば確認出来そうですが。
sazi

2019/04/24 07:16

因みにネットワーク要因ではないですよね? 集計しない状態でのSELECTは十分早いですか?
guest

回答2

0

dtDateTimeとは別にmonthデータを保持して、そのカラムにインデックスを設定しておけば
無駄な計算が減るので高速化が期待できます。

もしくはDATEPART(MONTH,dtDateTime)でgroup byしてcount(*)したものを
サブクエリにして展開してはどうでしょうか?

投稿2019/04/24 04:12

yambejp

総合スコア114572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

1つのSELECT句で全ての集計を行っているので
1レコードを出力するために、複数回検索をかけて絞り集計しています。
1レコード出力するのに12回検索して12回集計している感じだと思います。

WITH句を用いて中間テーブルを挟み、集計しやすくデータを加工するといいと思います。

WITH A AS( --dtDateTime列を集計用に展開 SELECT organNum ,timeUnit ,DATEPART(MONTH,dtDateTime) as count_month_flag FROM テーブル ),B AS( --月別での集計値 SELECT organNum ,timeUnit ,count_month_flag ,count(*) count_month FROM A GROUP BY organNum ,timeUnit ,count_month_flag ),C AS( --縦持ちから横持ちへ SELECT organNum ,timeUnit ,CASE WHEN count_month_flag = 4 THEN count_month ELSE 0 END AS month4 ,CASE WHEN count_month_flag = 5 THEN count_month ELSE 0 END AS month5 ,CASE WHEN count_month_flag = 6 THEN count_month ELSE 0 END AS month6 ,CASE WHEN count_month_flag = 7 THEN count_month ELSE 0 END AS month7 ,CASE WHEN count_month_flag = 8 THEN count_month ELSE 0 END AS month8 ,CASE WHEN count_month_flag = 9 THEN count_month ELSE 0 END AS month9 ,CASE WHEN count_month_flag = 10 THEN count_month ELSE 0 END AS month10 ,CASE WHEN count_month_flag = 11 THEN count_month ELSE 0 END AS month11 ,CASE WHEN count_month_flag = 12 THEN count_month ELSE 0 END AS month12 ,CASE WHEN count_month_flag = 1 THEN count_month ELSE 0 END AS month1 ,CASE WHEN count_month_flag = 2 THEN count_month ELSE 0 END AS month2 ,CASE WHEN count_month_flag = 3 THEN count_month ELSE 0 END AS month3 FROM B ) --穴埋め処理 SELECT organNum ,timeUnit ,SUM(month4) as '4月' ,SUM(month5) as '5月' ,SUM(month6) as '6月' ,SUM(month7) as '7月' ,SUM(month8) as '8月' ,SUM(month9) as '9月' ,SUM(month10) as '10月' ,SUM(month11) as '11月' ,SUM(month12) as '12月' ,SUM(month1) as '1月' ,SUM(month2) as '2月' ,SUM(month3) as '3月' FROM C GROUP BY organNum ,timeUnit ; ※実行検証はしていないため悪しからず…

投稿2019/04/24 05:16

Toshi_1995

総合スコア40

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2019/04/24 06:40

>1レコードを出力するために、複数回検索をかけて絞り集計しています。 そんな動作はしません。 そのWITH式は単にインラインビューでネストしているのと変わりません。 自己結合でもないので、WITH式にしてもレスポンスは向上しないと思いますよ。
Toshi_1995

2019/04/24 06:49

ご指摘ありがとうございます。 大変恐縮ですが、レスポンスを向上させるには、どのような書き方ありますでしょうか?
sazi

2019/04/24 07:07 編集

質問の記述はクロス集計として一般的だと思います。 ですので、書き方よりインデックスの設定だと思います。 質問にはその情報が無いので、回答は出来ませんが。
Toshi_1995

2019/04/24 07:10

ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問