在结果行中选择多个相关记录

时间:2013-09-27 13:33:46

标签: sql ms-access select

我目前正在为MS-Access数据库编写导出函数,我不太清楚如何编写一个查询,以便给出我想要的结果。
我想做的是以下几点:

假设我有一个表Error,并且表Cause与表ErrorCause建立了多对多的关系,由表select Error.ID, Cause.ID from ((Error inner join ErrorCauses on Error.ID = ErrorCauses.Error) left join Cause on ErrorCauses.Cause = Cause.ID) 建模。目前我有一个类似于此的查询(简化,原始也进一步关系):

{{1}}

我得到这样的东西:

 Error | Cause
 -------------
 12345 | 12    
 12345 | 23    
 67890 | 23    
 67890 | 34    

但我需要为每个错误选择第一个,比如3个原因的ID(即使它们是空的),所以它看起来像这样:

 Error | Cause1 | Cause2 | Cause3
 --------------------------------
 12345 | 12     | 23     |       
 67890 | 23     | 34     |       

有没有办法在单个查询中执行此操作? 就像选择Top 3然后将其展平为生成的行一样? 提前感谢任何指针。

1 个答案:

答案 0 :(得分:1)

您的要求是针对特定数量的原因 - 3。这使得通过在同一子查询上进行三向连接,可以在同一行上获得三个不同的原因,这是可行和可管理的。

首先,让我们将您的错误和原因查询定义为直接的Access查询(QueryDef对象,如果您想要技术性的话)。

qryErrorCauseInfo

select
  Error.ID as ErrorID
, Cause.ID as CauseID
from (Error
inner join ErrorCauses
on Error.ID = ErrorCauses.Error)
left outer join Cause
on ErrorCauses.Cause = Cause.ID

顺便说一下,我觉得上面左边的连接应该是一个内连接,因为我在my comment中提到过。

接下来,让我们进行三向连接,以获得行中可能的原因组合:

qryTotalCause

select distinct
  *
, iif(Cause1 is null, 0, 1)
+ iif(Cause2 is null, 0, 1)
+ iif(Cause3 is null, 0, 1) as TotalCause
from (
  select
    eci1.ErrorID
  , eci1.CauseID as Cause1
  , iif(eci2.CauseID = Cause1, null, eci2.CauseID) as Cause2
  , iif(
      eci3.CauseID = Cause1 or eci3.CauseID = Cause2
    , null
    , eci3.CauseID
    ) as Cause3
  from (qryErrorCauseInfo as eci1
  left outer join qryErrorCauseInfo as eci2
  on eci1.ErrorID = eci2.ErrorID)
  left outer join qryErrorCauseInfo as eci3
  on eci2.ErrorID = eci3.ErrorID
) as sq
where (
  Cause1 < Cause2
  and Cause2 < Cause3
) or (
  Cause1 < Cause2
  and Cause3 is null
) or (
  Cause2 is null
  and Cause3 is null
) or (
  Cause1 is null
  and Cause2 is null
  and Cause3 is null
)

最后,我们需要一个相关的子查询来为每个错误选择具有最多原因的一行(其余行只是相同原因的不同排列):

select
  ErrorID
, Cause1
, Cause2
, Cause3
from qryTotalCause as tc1
where tc1.TotalCause = (
  select max(tc2.TotalCause)
  from qryTotalCause as tc2
  where tc1.ErrorID = tc2.ErrorID
)

简单! (不是: - )