私は現在、特に複雑なユースケースに取り組んでいます。以下の簡略化:)
第 1 に、クライアント レコードは、サービスのコレクションと多対 1 の関係にあります。つまり、1 つのクライアントに複数のサービスが関連付けられている場合があります。
トリガー内で、特定の基準に基づいてクライアントの ID を返すクエリを作成しています。基準は次のとおりです。
- タイプ B のサービスが少なくとも 1 つあり、タイプ A のサービスが存在しない場合は、id を返します。
- タイプ C のサービスが少なくとも 1 つあり、タイプ B または A のサービスが存在しない場合は、id を返します。
- 少なくとも 1 つのサービスがタイプ D であり、タイプ C または B または A のサービスが存在しない場合は、id を返します。
私の現在のアプローチは、以下のようなクエリを作成することです
SELECT c.ClientId
FROM
Clients AS c
-- actually INNER JOIN is superfluous in this sample, but required for
-- other auxilliary criteria i have left out. illustrates relationship
-- between Clients and Services table
INNER JOIN Services AS s ON c.ClientId = s.ClientId
WHERE
-- has at least one service of type B, no A
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A'))) OR
-- has at least one service of type C, no B, no A
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'C')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A'))) OR
-- has at least one service of type D, no C, no B, no A
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'D')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'C')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A')))
where[dbo].[Get_ServicesByClientIdAndType]
は、指定されたクライアント ID とサービス タイプに関連付けられたサービスを返す関数です。に似ている
-- this query is actually significantly more complex than shown
-- below, but this illustrates use of parameters client id and
-- service type
SELECT s.ServiceType
FROM
Services AS s
WHERE
s.ClientId = @clientId AND
s.ServiceType = @serviceType
これがこのユースケースを表現する最適な手段であると仮定すると、関数[dbo].[Get_ServicesByClientIdAndType]
のサブクエリはキャッシュされますか、それともサービスパラメーターを変更すると、呼び出しごとに新しい評価が必要になりますか? [私はこのことを 9 回呼び出しています!!! Sql Server 2005 を実行中]
Sql Server 2005 が結果のキャッシュなど、いくつかのサブクエリの最適化をサポートしていることは知っていますが、どのような状況下で、またはどのようにサブクエリ [または関数] を作成して、Sql Server の機能を最大限に活用できるかはわかりません。
編集:上記の私の基準を見直し、何かがおかしいというしつこい感覚を手放すことができませんでした. 私は頭の中でいくつかのロジックをいじって、この[はるかに単純な]定式化を思いつきました
SELECT c.ClientId
FROM
Clients AS c
INNER JOIN Services AS s ON c.ClientId = s.ClientId
WHERE
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A')) AND
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) OR
EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'C')) OR
EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'D')))
基本的に、C と D の場合と同様に、拒否につながる B に関するシナリオは存在しないため、どのような構成でも受け入れられます。A がどの選択にも存在しないことだけを気にします。アーグ!チャーリー・ブラウン!
両方の式をレビューのために残しておきますが、ユーザー定義関数に関する Sql Server のパフォーマンスに関する回答には非常に感謝しています。