0

我必须在桌子上做一个自我加入。我正在尝试返回几列的列表,以查看在同一天(MM/DD/YYYY)执行了多少每种类型的药物测试,其中至少完成了两项测试,其中至少一项导致了'UN'的结果代码。

我正在加入其他表格以获取如下信息。问题是我不太明白如何排除那些只有一个结果行的人,他们当天确实有一个“联合国”结果,但当天没有任何其他测试。

查询结果(列)

县、DrugTestID、ID、名称、CollectionDate、DrugTestType、结果、计数(DrugTestType)

我有几行 ID 12345 是正确的。但是 ID 12346 是单行,其中显示他们的行结果为 count (1)。他们在这一天得到了“联合国”的结果,但那天他们没有进行任何其他测试。我想排除这个。

我尝试了以下查询

选择  
    c.desc 为“县”,
    dt.pid 作为“PID”,
    dt.id 作为 'DrugTestID',
    p.id 作为“ID”,
    bio.FullName 为“参与者”,
    转换(varchar,dt.CollectionDate,101)为'CollectionDate',       
    dtt.desc 作为“药物测试类型”,
    dt.result 作为结果,
    计数(dt.dru_drug_test_type)作为“测试类型计数”
从    
    dbo.Test as dt with (nolock)
       在 dt.pid = h.id 上以 h 身份加入 dbo.History
       在 h.pid = p.id 上以 p 身份加入 dbo.Participant
       在 bio.id = p.id 上加入 BioData 作为 bio
       在 p.CountyCode = c.code 上加入 County as c with (nolock)
       在 dt.DrugTestType = dtt.code 上加入 DrugTestType 作为 dtt 与 (nolock)
       内部联接
          (
             选择不同的
                dt2.pid,
                CONVERT(varchar, dt2.CollectionDate, 101) as 'CollectionDate'
             从   
           dbo.DrugTest as dt2 with (nolock)
                   在 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
            和转换(varchar,dt.CollectionDate,101)=转换(varchar,派生。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

如果我理解这个问题,这种查询的基本模式就是在你的联接中包含否定或排除条件。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 回答
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 回答