0

テーブルで自己結合を行う必要があります。いくつかの列のリストを返して、少なくとも 2 つのテストが行​​われ、そのうちの少なくとも 1 つが「UN」の結果コード。

以下のように情報を取得するために他のテーブルに参加しています。問題は、ある日に「国連」の結果があったが、その日に他の検査を受けていない単一の結果行を持つ人を除外する方法がよくわからないことです.

クエリ結果 (列)

郡、DrugTestID、ID、名前、CollectionDate、DrugTestType、Results、Count(DrugTestType)

ID 12345 の正しい行がいくつかあります。しかし、ID 12346 は単一の行であり、行の結果が count (1) であることを示しています。彼らはこの日に「UN」の結果を出しましたが、その日は他の検査はありませんでした。これを除外したい。

次のクエリを試しました

選択する  
    c.desc を「郡」として、
    「PID」としてのdt.pid、
    dt.id を「DrugTestID」として、
    p.id を「ID」として、
    「参加者」としての bio.FullName、
    CONVERT(varchar, dt.CollectionDate, 101) as 'CollectionDate',       
    「Drug Test Type」としてのdtt.desc、
    結果としてのdt.result、
    COUNT(dt.dru_drug_test_type) as 'Count Of Test Type'
から    
    dbo.Test as dt with (nolock)
       dt.pid = h.id で dbo.History を h として結合します。
       h.pid = p.id で p として dbo.Participant に参加します
       BioData に bio.id = p.id の bio として参加します
       p.CountyCode = c.code で (nolock) を使用して County を c として結合します。
       dt.DrugTestType = dtt.code で (nolock) を使用して、DrugTestType を dtt として結合します。
       内部結合
          (
             個別に選択
                dt2.pid、
                CONVERT(varchar, dt2.CollectionDate, 101) as 'CollectionDate'
             から   
           (nolock) を使用した dt2 としての dbo.DrugTest
                   dt2.pid = h2.id で dbo.History を h2 として結合します。
                   h2.pid = p2.id で p2 として dbo.Participant に参加します
             どこ
                dt2.result = '国連'
                および '11-01-2011' と '10-31-2012' の間の dt2.CollectionDate
                および p2.DrugCourtType = 'AD'
          ) 派生として
            dt.pid = 派生.pid で
            そして convert(varchar, dt.CollectionDate, 101) = convert(varchar, derived.CollectionDate, 101)
グループ化
   c.desc、dt.pid、p.id、dt.id、bio.fullname、dt.CollectionDate、dtt.desc、dt.result
注文
    c.desc ASC、参加者 ASC、dt.CollectionDate ASC
4

2 に答える 2

0

クエリにはテストごとに個別の行があるため、これは少し複雑です。必要な情報を取得するには、ウィンドウ/分析関数を使用する必要があります。これらを使用すると、集計関数を計算できますが、各行に値を入力できます。

次のクエリは、クエリから始まります。次に、各参加者の各日付の国連結果の数とテストの総数を計算します。適切なフィルターを適用して、必要なものを取得します。

with base as (<your query here>)
select b.*
from (select b.*,
             sum(isUN) over (partition by Participant, CollectionDate) as NumUNs,
             count(*) over (partition by Partitipant, CollectionDate) as NumTests
      from (select b.*,
                  (case when result = 'UN' then 1 else 0 end) as IsUN
            from base
           ) b
     ) b
where NumUNs <> 1 or NumTests <> 1

句またはウィンドウ関数がないwithと、同じことを行うために特に醜いクエリを作成できます。

select b.*
from (<your query>) b join
     (select Participant, CollectionDate, count(*) as NumTests,
             sum(case when result = 'UN' then 1 else 0 end) as NumUNs
      from (<your query>) b
      group by Participant, CollectionDate
     ) bsum
     on b.Participant = bsum.Participant and
        b.CollectionDate = bsum.CollectionDate
where NumUNs <> 1 or NumTests <> 1
于 2012-11-09T15:05:13.270 に答える
0

私が問題を理解している場合、この種のクエリの基本的なパターンは、結合に否定または除外条件を含めることです。IE、列 A は一致するが、列 B と C は一致しない自己結合:

select
  [columns]

from
  table t1
  join table t2 on (
    t1.NonPkId = t2.NonPkId
    and t1.PkId != t2.PkId
    and t1.category != t2.category
  )

ベンチマークがより適切な場合は、条件を WHERE 句に入れます。

select
  [columns]

from
  table t1
  join table t2 on (
    t1.NonPkId = t2.NonPkId
  )

where
    t1.PkId != t2.PkId
    and t1.category != t2.category

多くの場合、自己結合から始めるのが最も簡単で、それをすべての関連情報を結合する「ベース テーブル」として扱います。

select
  [columns]

from
  (select
    [columns]

  from
    table t1
    join table t2 on (
      t1.NonPkId = t2.NonPkId
    )

  where
      t1.PkId != t2.PkId
      and t1.category != t2.category
  ) bt

  join [othertable] on (<whatever>)
  join [othertable] on (<whatever>)
  join [othertable] on (<whatever>)

これにより、他のテーブルから干渉されることなく、その自己結合を正しく行うことに集中できます。

于 2012-11-09T15:52:14.990 に答える