【问题标题】:Selecting a number of related records into a result row在结果行中选择多个相关记录
【发布时间】:2013-09-27 13:33:45
【问题描述】:

我目前正在为 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)

我得到这样的东西:

错误 |原因 ------------- 12345 | 12 12345 | 23 67890 | 23 67890 | 34

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

错误 |原因1 |原因2 |原因3 -------------------------------- 12345 | 12 | 23 | 67890 | 23 | 34 |

有没有办法在单个查询中做到这一点? 喜欢选择前 3 名,然后将其展平到结果行中? 在此先感谢您的任何指点。

【问题讨论】:

  • 看看 SQL Server Pivot 命令。
  • @asantaballa 这不是 sql server
  • 啊,对不起。看到 MS 和 SQL,我的脑子就掉线了。请忽略。
  • 之后你对查询做了什么?

标签: sql ms-access select


【解决方案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

顺便说一下,我觉得上面的left join应该是inner join,原因我在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
)

简单! (不是:-)

【讨论】:

  • 哇,这比我想象的要复杂一些。我会在星期一试试这个,让你知道它是如何工作的。 :)
  • 是的,使用同一个表三次的三向连接会创建很多我们需要删除的多余结果行。这就是大部分复杂性所在。但是刚刚测试了整个事情,我相信它可以工作?虽然可能有点慢。
  • 经过一些调整后,这确实有效:) 我仍然需要弄清楚如何为每个原因获得 5 个解决方案,但这对我来说是一个很好的起点。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-01
  • 2015-02-15
相关资源
最近更新 更多