2017-01-06 18 views
0

人テーブル、予定テーブル、およびリマインダーテーブルを検索するクエリを実行しようとしています。条件が満たされない場合に3つのテーブルのSQL結合問題が結果を返す

私は少なくとも1つのアポイントメントを持っている人、将来のアポイントメントを持っていない人、システムにアクティブなリマインダを持っていない人のみを返信したいと思います。

SELECT p.person_ID 
from people p 
WHERE exists (
select 1 from appointments e where e.person_id=p.person_id 
    AND e.appt_kept_ind='Y') 
AND not exists (
    select 1 from appointments s where s.person_id=p.person_id 
    AND CONVERT(DateTime, s.apptdate, 112) > CURRENT_TIMESTAMP)) 
AND not exists (
    select 1 from reminder re where re.person_id=p.person_id 
    AND CONVERT(DateTime, re.return_date, 112) > CURRENT_TIMESTAMP) 

編集:フィードバックを取った後、左の結合を削除しました。私は、問題の1つが誰かがアクティブリマインダーを持っているアクティブな「y」であることに気づいたが、リマインダーは過去であっても「アクティブ」である可能性があるので、それらのレコードを除外します。

編集:私はいくつかの問題を持っているスキーマ

Person 
    person_id UniqueIdentifier NOT NULL PK 
    firstname nvarchar NOT NULL 
    lastname nvarchar NOT NULL 
    .... 

Appointments 
    appointment_ID uniqueidentifier NOT NULL PK 
    person_ID uniqueidentifier NOT NULL 
    apptdate nvarchar NOT NULL 
    apptKept nvarchar (N or Y) 

Reminder 
    reminder_id uniqueidentifier NOT NULL PK 
    person_ID uniqueidentifier NOT NULL 
    return_date nvarchar NOT NULL 
    Active nvarchar (N or Y) 

のための要求は:人々の複数の結果を返す、私も私が必要とするすべてのデータは、人々のテーブルにある場合、参加する必要がありますか?最後に、かなり遅いです。

+0

私はそれが両方のテーブルから一致するものを返すようになりますし、複製を作成しますa.keptが何を知っているが、2つのテーブルを結合左いけません同じテーブルの2つのエントリをヒットした場合のエントリそのため、1人のユーザーに対して2つの予定が存在する場合、その参加のために人物の行が重複して表示されます。それらのサブセレクトに基づいてすべてのフィルタリングを行っているようですので、おそらくジョインは必要ないと思います。左のジョインも内部のジョインよりも遅いので、パフォーマンスの問題のいくつかを説明するかもしれません – thsorens

+0

投稿した後、もう少し作業しました: – DDulla

答えて

0

の心に入って来るビューのものがあります。

  1. 人が複数の予定または複数のリマインダー(による左への参加を)持っている場合は、追加の列を取得するには、ところで、私はあなたが結果を利用しないので、ここにリマインダに参加する必要があるとは思わない。
  2. 2つの左結合の後にwhere-partで相関サブクエリを使用します。理論的には、このサブクエリのそれぞれは、この結合によって返された(おそらく複写された)タプルのそれぞれについて評価されます。データによっては、無関係のサブクエリが高速であると仮定します。

以下を試してください(スキーマなしで試してみることはできません)。アプローチは、すべての人のために評価するテーブルappaggrを用意して、kept(最大タプルがある場合はYである必要があります)のアポイントをチェックして、同じ実行で最新のアポイントメントを評価します将来予定がない場合はcurrent_timestamp)。このテーブルと人のテーブルへの参加(注記:参加していないことに注意してください)に参加すると、予定を持っていて将来の予定がないすべての人が返されます。さらに、リマインダをチェックすることは、無関係のサブクエリに変換されます。アクティブなアラームで多くの人々に存在しない場合、これはより効率的に作業する必要があります

SELECT p.firstname, p.lastname, p.person_ID, 
from people p 
join (select a.person_id, max(a.kept) as maxkept, max(CONVERT(DateTime, a.apptdate, 112)) as maxdate 
      from appointments a 
      group by a.person_id 
      having maxkept='Y' and maxdate <= CURRENT_TIMESTAMP) appaggr on p.person_id = appaggr.person_id 
where p.person_id not in (select r.person_id from reminder r where r.active='Y') 
+0

あなたのクエリを使用しようとすると、maxkept定義されていません – DDulla

関連する問題