を取得したいのですが。実際にIDだけが必要な場合は、2段階クエリを実行することも1つの選択肢です。
select s1.id
from staff s1
where exists (select 1
from staff s3
where s1.id = s3.id
and s1.position <> s3.position
and (s1.start_date, coalesce(s1.end_date, 'infinity'::date)) overlaps (s3.start_date, coalesce(s3.end_date, 'infinity'::date))
)
null
として缶」:
select s1.id
from staff s1
where exists (select 1
from staff s2
where s1.id = s2.id
and s1.position <> s2.position)
あなたが使用することができ、同時に複数のポジションを持っていたものを取得するには:
まず、複数のポジションを持っているすべての行を取得します比較するには、null
の値をend_date
に置き換えて、他のすべての日付よりも大きい日付にする必要があります。これはcoalesce(s3.start_date, 'infinity'::date)
の機能です。 overlaps
演算子は、重複する日付範囲をチェックします。
select s1.id
from staff s1
where exists (select 1
from staff s2
where s1.id = s2.id
and s1.position <> s2.position)
except
select s1.id
from staff s1
where exists (select 1
from staff s3
where s1.id = s3.id
and s1.position <> s3.position
and (s1.start_date, coalesce(s1.end_date, 'infinity'::date)) overlaps (s3.start_date, coalesce(s3.end_date, 'infinity'::date))
)
;
:
をあなたはEXCEPT
演算子でこれらを組み合わせると、あなたが希望する結果を得るCOALESCEでdate '9999-12-31'
のようなものを使用しても動作しますが、infinity
を使用すると、(少なくとも私の目には)これがより明示的になります
id
--
1
3
を使用すると、すべての列とすべてのPOSITが必要な場合:あなたのサンプルデータについて上記のクエリが返す
イオン(の代わりにのID)を使用すると、別のアプローチをとることができます。
まずポジションをオーバーラップしていないすべての行を取得:
select s1.*
from staff s1
where not exists (select 1
from staff s2
where s1.id = s3.id
and s1.position <> s3.position
and (s1.start_date, coalesce(s1.end_date, 'infinity'::date)) overlaps (s2.start_date, coalesce(s2.end_date, 'infinity'::date))
)
以上ももはやアクティブ位置とID = 0を持つ行が含まれますので、我々が持っているすべてのこれらの行を削除する必要があります複数の位置:あなたのサンプルデータについては
select *
from (
select s1.*,
count(*) over (partition by s1.id) as cnt
from staff s1
where not exists (select 1
from staff s2
where s1.id = s2.id
and s1.position <> s2.position
and (s1.start_date, coalesce(s1.end_date, 'infinity'::date)) overlaps (s2.start_date, coalesce(s2.end_date, 'infinity'::date))
)
) t
where cnt > 1;
は、上記戻ります:
id | position | start_date | end_date | cnt
---+-----------+------------+------------+----
1 | staff | 2005-01-01 | 2006-01-01 | 2
1 | assistant | 2006-01-02 | | 2
3 | driver | 2005-01-01 | 2007-01-01 | 3
3 | operator | 2007-01-02 | | 3
3 | intern | 2002-01-01 | 2002-03-01 | 3
これが最も効率的な方法であるかどうかはわかりませんが、今は別のものを考えることはできません。