在V6R1的DB2fori(又称DB2/400)中,我想编写一个SQLSELECT语句,它从一个头记录中返回一些列,从一个匹配的详细记录中只返回一些列。它可以是任何匹配的记录,但我只想要其中一个的信息。我可以通过下面的查询来实现这一点,但我认为必须有一种比使用with子句更简单的方法。如果我需要的话,我会用它,但我一直在想,"一定有更简单的方法"。本质上,我只是从Person表中返回firstName和lastName。。。加上PersonEmail表中的一个匹配电子邮件地址。
谢谢!
with theMinimumOnes as (
select personId,
min(emailType) as emailType
from PersonEmail
group by personId
)
select p.personId,
p.firstName,
p.lastName,
pe.emailAddress
from Person p
left outer join theMinimumOnes tmo
on tmo.personId = p.personId
left outer join PersonEmail pe
on pe.personId = tmo.personId
and pe.emailType = tmo.emailType
PERSONID FIRSTNAME LASTNAME EMAILADDRESS
1 Bill Ward p1@home.com
2 Tony Iommi p2@cell.com
3 Geezer Butler p3@home.com
4 John Osbourne -
这听起来像是row_number()
:的工作
select p.personId, p.firstName, p.lastName, pe.emailAddress
from Person p left outer join
(select pe.*,
row_number() over (partition by personId order by personId) as seqnum
from PersonEmail pe
) pe
on pe.personId = tmo.personId and seqnum = 1;
如果从PersonEmail文件中选择哪一行确实无关紧要,那么几乎没有理由执行摘要查询或OLAP查询来选择该行;根据CTE的MIN聚合,前者隐含排序,后者明确要求排序。FETCH FIRST子句的以下使用应该足够了,而不需要对辅助文件中的数据的ORDER有任何要求[仅仅是任何匹配的行;尽管可能是第一行或最后一行,取决于personId密钥,尽管完全取决于查询实现,甚至可能不使用密钥]:
select p.personId, p.firstName, p.lastName
, pe.emailAddress
from Person as p
left outer join lateral
( select pe.*
from PersonEmail pe
where pe.personId = p.personId
fetch first 1 row only
) as pe
on p.personId = pe.personId