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

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

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

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

SQL

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

Q&A

解決済

2回答

623閲覧

SQLによるレコードの統合処理

kakutus

総合スコア2

SQL Server

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

SQL

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

0グッド

0クリップ

投稿2022/05/30 06:53

編集2022/05/30 06:56

SQLによるレコードの統合処理を行いたいです。
実際に想定通り動くSQLは組めたのですが、重くて使い物になりません。
パフォーマンスの改善方法、もしくは別の案などがあれば教えていただきたいです。

実現したいこと

以下具体例です。

次のようなテーブルAがあったとします。

テーブルA

会社名取引先名取引金額
A社hoge社10000
A社fuga社2000
A社piyo社3000
B社hoge社40000
B社fuga社5000
B社puyo社6000
C社hoge社7000
C社fuga社8000

ここでfuga社がhoga社に吸収され、以下のようにテーブルを更新する必要が出てきました。

会社名取引先名取引金額
A社hoge社12000
A社piyo社3000
B社hoge社45000
B社puyo社6000
C社hoge社15000

前提として、元のテーブルAの取引先には会社名1つに対して必ずhoge社とfuga社が1つずつ入っています。

発生している問題

目的の処理を実現するために以下のようなSQLを作成しました。

SQL

1DECLARE @CompanyName NVARCHAR(100); 2 3 DECLARE crTriggerList CURSOR 4 FOR 5 SELECT DISTINCT [会社名] AS CompanyName --会社名の一覧 6 FROM [テーブルA] 7 8 OPEN crTriggerList; 9 10 FETCH NEXT FROM crTriggerList 11 INTO @CompanyName; 12 13 WHILE @@FETCH_STATUS = 0 14 BEGIN 15 DECLARE @Price DECIMAL(12,0); 16 17 --統合前の合計 18 SELECT @Price = SUM(取引金額) 19 FROM [テーブルA] 20 WHERE 会社名 = @CompanyName 21 AND (取引先名= 'hoge' 22 OR 取引先名 = 'fuga') 23 24 --統合した計算結果で更新 25 UPDATE テーブルA 26 SET 取引金額 = @Price 27 FROM [テーブルA] 28 WHERE 会社名 = @CompanyName 29 AND 取引先名= 'hoge' 30 31 --吸収された会社削除 32 DELETE FROM [テーブルA] 33 WHERE 会社名 = @CompanyName 34 AND 取引先名= 'fuga' 35 36 FETCH NEXT FROM crTriggerList --会社名ごとに上記の処理を繰り返す 37 INTO @CompanyName; 38 END 39 40 CLOSE crTriggerList; 41 DEALLOCATE crTriggerList; 42

一応これで期待通りの結果は得られるのですが、レコードが増えると時間がかかりすぎてしまいます。
パフォーマンスの改善方法、もしくはカーソル処理を使わない別の案などがあれば教えていただきたいです。

よろしくお願いします。

補足情報(FW/ツールのバージョンなど)

Microsoft SQL Server Management Studio 18
Microsoft SQL Server 2019 (RTM-GDR) (KB4583458) - 15.0.2080.9 (X64) Nov 6 2020 16:50:01 Copyright (C) 2019 Microsoft Corporation Enterprise Edition (64-bit) on Windows Server 2019 Datacenter 10.0 <X64> (Build 17763: ) (Hypervisor)

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

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

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

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

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

maisumakun

2022/05/30 06:59

> レコードが増えると時間がかかりすぎてしまいます。 定期的に行う処理ではないと思うのですが、どの程度の件数に対してどの程度時間がかかるのでしょうか。
kakutus

2022/05/30 07:16 編集

maisumakun さん 1000件のレコードに対して更新をかけたところ10分程度かかりました。 対象のレコードは200万件程あるので、単純計算でも20000分、およそ13日もかかってしまいます…。 せめて1日で終わるようにはしたいです。
guest

回答2

0

ベストアンサー

1000件のレコードに対して更新をかけたところ10分程度かかりました。

これって、200万の内1,000件って事ですよね?
※そうでないと、質問に上げていない条件が含まれていない限り、全体で1,000件なら遅すぎます。

少なくとも(会社名, 取引先名)のインデックスが無いと遅いと思われます。

手打ちで検証もしていませんが、updateだけ記述してみました。

SQL

1UPDATE テーブルA dst 2SET 取引金額 = src.統合額 3from ( 4 select 会社名, sum(取引金額) 統合額 5 from テーブルA ta 6 WHERE 取引先名 in ('hoge', 'fuga') 7 and exists (select 1 from [テーブルA] where 会社名=ta.会社名 and 取引先名= 'hoge') 8 and exists (select 1 from [テーブルA] where 会社名=ta.会社名 and 取引先名= 'fuga') 9 group by 会社名 10) src 11where dst.会社名=src.会社名 12 and dst.取引先名='hoge'

ただ、後から統合前の状態も必要とかにならないなら良いですけど、データ規模からすると有り得そうな気もします。

投稿2022/05/30 07:41

編集2022/05/30 13:45
sazi

総合スコア25195

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

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

kakutus

2022/05/30 09:03

圧倒的に早くなりました!ありがとうございました。 使い方次第でしょうけどすぐFETCHに頼るのは良くないということがわかりました…。 >ただ、後から統合前の状態も必要とかにならないなら良いですけど、データ規模からすると有り得そうな気もします。 そこはバックアップがあるので問題ありません。ご親切にありがとうございます。
guest

0

SELECT 会社名, SUM(取引金額) WHERE 取引先名 IN('hoge', 'fuga') GROUP BY 会社名のような集計を行って、それで一気に置き換えるような方向性を考えたほうがいいのではないでしょうか。

投稿2022/05/30 07:36

編集2022/05/30 07:37
maisumakun

総合スコア145184

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

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

kakutus

2022/05/30 09:07

方針はほぼ同じでしたが、具体的なコードを載せていただいたsaziさんの回答をベストアンサーにしました。 迅速な回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問