プログラムで構築されたより大きなselectステートメント内のサブクエリであるselectステートメントがあります。問題は、このサブクエリを含めることを選択すると、ボトルネックとして機能し、クエリ全体が非常に遅くなることです。
データの例は次のとおりです。
Payment
.Receipt_no|.Person |.Payment_date|.Type|.Reversed|
2|John |01/02/2001 |PA | |
1|John |01/02/2001 |GX | |
3|David |15/04/2003 |PA | |
6|Mike |26/07/2002 |PA |R |
5|John |01/01/2001 |PA | |
4|Mike |13/05/2000 |GX | |
8|Mike |27/11/2004 |PA | |
7|David |05/12/2003 |PA |R |
9|David |15/04/2003 |PA | |
サブクエリは次のとおりです。
select Payment.Person,
Payment.amount
from Payment
inner join (Select min([min_Receipt].Person) 'Person',
min([min_Receipt].Receipt_no) 'Receipt_no'
from Payment [min_Receipt]
inner join (select min(Person) 'Person',
min(Payment_date) 'Payment_date'
from Payment
where Payment.reversed != 'R' and Payment.Type != 'GX'
group by Payment.Person) [min_date]
on [min_date].Person= [min_Receipt].Person and [min_date].Payment_date = [min_Receipt].Payment_date
where [min_Receipt].reversed != 'R' and [min_Receipt].Type != 'GX'
group by [min_Receipt].Person) [1stPayment]
on [1stPayment].Receipt_no = Payment.Receipt_no
これは、.Payment_date (昇順)、.Receipt_no (昇順) で各人の最初の支払いを取得します。ここで、.type は「GX」ではなく、.Reversed は「R」ではありません。次のように:
Payment
.Receipt_No|.Person|.Payment_date
5|John |01/01/2001
3|David |15/04/2003
8|Mike |27/11/2004
Ahmadsの投稿に続いて -
以下の結果から
(3|David |15/04/2003)
and (9|David |15/04/2003)
私は、最低のレシート番号を持つレコードだけが欲しいです。そう
(3|David |15/04/2003)
そこで、集計関数 'min(Payment.receipt_no)' を追加して、個人別にグループ化しました。
クエリ 1。
select min(Payment.Person) 'Person',
min(Payment.receipt_no) 'receipt_no'
from
Payment a
where
a.type<>'GX' and (a.reversed not in ('R') or a.reversed is null)
and a.payment_date =
(select min(payment_date) from Payment i
where i.Person=a.Person and i.type <> 'GX'
and (i.reversed not in ('R') or i.reversed is null))
group by a.Person
これをはるかに大きなクエリ内のサブクエリとして追加しましたが、それでも実行速度は非常に遅かったです。そのため、集計関数の使用を避けながらクエリを書き直そうとしたところ、次のようになりました。
クエリ 2。
SELECT
receipt_no,
person,
payment_date,
amount
FROM
payment a
WHERE
receipt_no IN
(SELECT
top 1 i.receipt_no
FROM
payment i
WHERE
(i.reversed NOT IN ('R') OR i.reversed IS NULL)
AND i.type<>'GX'
AND i.person = a.person
ORDER BY i.payment_date DESC, i.receipt_no ASC)
これは必ずしもより効率的だとは思いません。実際、より大きなデータ セットに対して 2 つのクエリを並べて実行すると、クエリ 1. は数ミリ秒で完了しますが、クエリ 2. は数秒かかります。
ただし、それらをはるかに大きなクエリ内のサブクエリとして追加すると、より大きなクエリはクエリ 1 を使用して数時間で完了し、クエリ 2 を使用して 40 秒で完了します。
これは、一方では集計関数を使用し、他方では使用していないことにのみ起因すると考えられます。