私は毎月約500kのレコードを持っています。 2ヶ月分のデータを選択する必要のあるレポートを作成しています。ユーザーは月を選択し、データは12ヶ月前のデータです。2か月間のデータを12カ月に分ける方法はありますか?
私の他の選択基準と、このデータが格納される方法によって、私は完全な結果セットを得るために同じクエリを4回実行する必要があることがわかります。これは私が最適な方法で実行するためのコードを必要とする意味 - 誰も画面がここで「ロード」;-)
を言いながら待って座って好きではない私が実行しているSQLです:
Declare @ReportDate DateTime
SET @ReportDate = dateadd(month,-1,DATEADD(month, DATEDIFF(month, 0, sysdatetime()), 0))
CREATE TABLE #DailyVolumes
(contract_name VARCHAR(50),
Volume INT,
date_registered DATETIME
);
INSERT into #DailyVolumes(contract_name, Volume, date_registered)
SELECT
CONCAT('L1-',a.contract_code) AS contract_name
,count(distinct(CONCAT(rtrim(p.lis_xxxx_id), '-', rtrim(r.lis_req_id)))) AS Volume
,a.date_registered
-- Create Temp Table to contain daily data
FROM accession a
Left join xxxx P on a.xxxx_id = p.xxxx_id
Left join requester R on a.requester_id = r.requester_id
where
(([date_registered] >= @ReportDate and [date_registered] < dateadd(month,1,@ReportDate))
OR ([date_registered] >= dateadd(month,-12,@ReportDate) and [date_registered] < dateadd(month,-11,@ReportDate)))
-- Limit results to L1
AND a.lis_code = 'L'
-- Limit results to Visitype NOT I or E
AND visit_type NOT IN('I', 'E')
GROUP BY
CONCAT('L1-',a.contract_code)
,a.date_registered
INSERT into #DailyVolumes(contract_name, Volume, date_registered)
SELECT
CONCAT('L1-',a.contract_code) AS contract_name
,count(distinct rtrim(r.lis_req_id)) AS Volume
,a.date_registered
-- Create Temp Table to contain daily data
FROM accession a
Left join xxxx P on a.xxxx_id = p.xxxx_id
Left join requester R on a.requester_id = r.requester_id
where
(([date_registered] >= @ReportDate and [date_registered] < dateadd(month,1,@ReportDate))
OR ([date_registered] >= dateadd(month,-12,@ReportDate) and [date_registered] < dateadd(month,-11,@ReportDate)))
-- Limit results to L1
AND a.lis_code = 'L'
-- Limit results to Visitype = I or E
AND visit_type IN('I', 'E')
GROUP BY
CONCAT('L1-',a.contract_code)
,a.date_registered
INSERT into #DailyVolumes(contract_name, Volume, date_registered)
SELECT
CONCAT('L2-',a.contract_code) AS contract_code
,count(distinct(CONCAT(rtrim(p.lis_xxxx_id), '-', rtrim(r.lis_req_id)))) AS Volume
,a.date_registered
FROM accession a
Left join xxxx P on a.xxxx_id = p.xxxx_id
Left join requester R on a.requester_id = r.requester_id
where
(([date_registered] >= @ReportDate and [date_registered] < dateadd(month,1,@ReportDate))
OR ([date_registered] >= dateadd(month,-12,@ReportDate) and [date_registered] < dateadd(month,-11,@ReportDate)))
-- Limit results to L2
AND a.lis_code = 'S'
-- Limit results to Visitype NOT I or E
AND visit_type NOT IN('I', 'E')
GROUP BY
CONCAT('L2-',a.contract_code)
,a.date_registered
INSERT into #DailyVolumes(contract_name, Volume, date_registered)
SELECT
CONCAT('L2-',a.contract_code) AS contract_code
,count(distinct rtrim(r.lis_req_id)) AS Volume
,a.date_registered
FROM accession a
Left join xxxx P on a.xxxx_id = p.xxxx_id
Left join requester R on a.requester_id = r.requester_id
where
(([date_registered] >= @ReportDate and [date_registered] < dateadd(month,1,@ReportDate))
OR ([date_registered] >= dateadd(month,-12,@ReportDate) and [date_registered] < dateadd(month,-11,@ReportDate)))
-- Limit results to L2
AND a.lis_code = 'S'
-- Limit results to Visitype = I or E
AND visit_type IN('I', 'E')
GROUP BY
CONCAT('L2-',a.contract_code)
,a.date_registered
-- SUM Daily Data into Monthly Slices
Select
sum(Volume) AS Volume
,contract_name
,DATEADD(MONTH, DATEDIFF(MONTH, 0, date_registered), 0) AS MonthRegistered
FROM #DailyVolumes
group by
contract_name
,DATEADD(MONTH, DATEDIFF(MONTH, 0, date_registered), 0)
ORDER BY MonthRegistered DESC
-- Clear Temp Table
DROP TABLE #DailyVolumes
このResultSetが取りますSSMSで約25秒戻ります。
私は4回ではなく8回のクエリを実行しようとしました。上記の日付句ごとに1回、結果セットを約6秒に戻しました。これはかなりOKですが直感的です... EDIT: - サーバーが結果をキャッシュしている必要があります。私はそれを1時間放置した後、私が期待していたような結果を得ました。実行には約48秒かかりました。 OR節を分割して、4つのクエリのそれぞれを2回目に実行すると、正味の利得はありません。
結果セットをより迅速に返す、より効率的なSQLがあるかどうかを知りたいと思います。私はこのようなORサテライトにサーバーに大きなオーバーヘッドをもたらすと信じていますが、これを単一の選択で実行するためのより良い方法は不明です。
EDIT:date_registeredは
はdate_registered上のインデックスがありますか? – scsimon
完全なクエリとテーブル構造を投稿できますか?インデックスを忘れないでください。また、実行計画を見ることは非常に役立ちます。 https://www.brentozar.com/pastetheplan/ –
残念ながら私はSHOWPLANの権限が拒否されています... – kiltannen