Sql 限制SELECT子查询中的行的更简单方法?
我在Oracle数据库上执行查询。假设我有一张桌子,各位。每个人都可以有多个参考号。参考号存储在不同的表ReferenceNumber中 ReferenceNumber包含一列PERSON_ID,该列与PEOPLE表的ID列相同。正是通过此ID连接表 假设我想在PEOPLE表上执行查询。但是,我只希望每个人记录返回一个参考号:即,如果一个人有多个参考号,我不希望每个参考号每个人返回多行 我为如何只选择一个参考号选择了一个标准:最早创建的参考号。参考号创建日期作为DATECREATED存储在ReferenceNumber表中 以下代码执行此任务:Sql 限制SELECT子查询中的行的更简单方法?,sql,oracle,Sql,Oracle,我在Oracle数据库上执行查询。假设我有一张桌子,各位。每个人都可以有多个参考号。参考号存储在不同的表ReferenceNumber中 ReferenceNumber包含一列PERSON_ID,该列与PEOPLE表的ID列相同。正是通过此ID连接表 假设我想在PEOPLE表上执行查询。但是,我只希望每个人记录返回一个参考号:即,如果一个人有多个参考号,我不希望每个参考号每个人返回多行 我为如何只选择一个参考号选择了一个标准:最早创建的参考号。参考号创建日期作为DATECREATED存储在Ref
SELECT
PEOPLE.ID,
PEOPLE.NAME,
PEOPLE.AGE,
PEOPLE.ADDRESS,
-- Subquery to return the earliest-created reference number for this person
(
SELECT
REFERENCENUMBERS.NUMBER
FROM
REFERENCENUMBERS
WHERE
REFERENCENUMBERS.PERSON_ID = PEOPLE.ID -- Link back to the main people ID
AND REFERENCENUMBERS.DATECREATED =
-- Sub-sub query simply to match the earliest date
(
SELECT
MIN(R.DATECREATED) -- To ensure that only the earliest-created reference number is returned.
FROM
REFERENCENUMBERS R -- Give this sub-sub query an alias for the table
WHERE
R.PERSON_ID = PEOPLE.ID -- Link back to the main people ID
)
)
FROM
PEOPLE
WHERE
PEOPLE.AGE > 18 -- Or whatever
然而,我要问的是,有知识的SQL人员。。有没有更简单的方法?仅仅为了查找最早的日期和限制子查询的WHERE子句而包含子查询似乎很麻烦
必须有一种更简单或更干净的方法来做到这一点。有什么建议吗
(顺便说一下,示例代码与我实际使用的代码相比大大简化了。请不要提供使用不同样式联接等实质性修改我的主要查询的答案-谢谢)。试试这个
SELECT
PEOPLE.ID,
PEOPLE.NAME,
PEOPLE.AGE,
PEOPLE.ADDRESS,
REFERENCENUMBERS.NUMBER
FROM PEOPLE
JOIN REFERENCENUMBERS ON REFERENCENUMBERS.PERSON_ID = PEOPLE.ID -- Link back to the main people ID
JOIN
(
SELECT
R.PERSON_ID,
MIN(R.DATECREATED) minc -- To ensure that only the earliest-created reference number is returned.
FROM
REFERENCENUMBERS R -- Give this sub-sub query an alias for the table
GROUP BY R.PERSON_ID
) t ON t.minc = REFERENCENUMBERS.DATECREATED and
t.PERSON_ID = REFERENCENUMBERS.PERSON_ID
WHERE
PEOPLE.AGE > 18 -- Or whatever
最简单的是top-n过滤器:
select people.id
, people.name
, people.age
, people.address
, ( select referencenumbers.number
from referencenumbers
where referencenumbers.person_id = people.id
order by referencenumbers.datecreated
fetch first row only )
from people
where people.age > 18;
(需要Oracle 12.1或更高版本。)
或此(适用于早期版本):
(为了便于阅读,我给了
referencenumbers
一个较短的别名。)为什么连接是不正确的?3个原因:首先,基本代码是由Business Objects应用程序生成的,它使用上述格式连接,编辑后我不想混淆。第二,正如我所说的,代码大大简化了我正在进行的工作,其中涉及多达10个不同的表,所有这些表都以各种方式链接。第三,我不是一个SQL专家,也不是一个非常基本的单连接的fait?是化名吗?它是如何定义的?您的第一次使用遵循MIN()计算:这只是用作该计算的别名吗?我的Oracle版本使用了“AS”这个词(例如选择PEOPLE.ID作为PERSONID)。或者你在做别的什么?我相信这两种语法都是有效的,但是是的,这是一个别名好的,谢谢大家-我会尝试看看我是否可以将它与那些连接一起工作到我的代码中(并找出它的意思:)。我会让你知道的,谢谢。正如拉尔夫提到的,“MIN(R.DATECREATED)minc”和“MIN(R.DATECREATED)AS minc”都可以用。它可以归结为编码标准和个人喜好。有些人(包括我自己)更喜欢指定AS,以明确这是一个别名。其他人不认为有必要,因为这是一个可选参数。再次感谢-我投票支持这个参数,因为我确信它会如所述工作,但是对于这些复杂的(对我来说)连接,我无法将它们应用到我实际使用的代码中(因为有太多具有复杂关系的表)。也许一位经验丰富的SQL专家能够做到这一点,但我无法理解将此应用于我实际使用的内容。但是再次谢谢,谢谢。我会试试这个-虽然我不熟悉KEEP和DENSE_RANK。我希望它能在我的甲骨文中起作用。(感谢您的编辑!)哦,添加了缺少的行。谢谢我很高兴地说,第二个“早期版本”的例子是有效的!再次感谢。我现在必须读一读关于KEEP、DENSE_RANK和FIRST的文章。据我所知,当你使用这些,它实际上并不重要,你是否使用最小或最大(如上所述)-对吗?或者错了…@ChrisMelville是的,如果同一日期有多个个人id,那么这只是一个决胜局。
select people.id
, people.name
, people.age
, people.address
, ( select min(rn.person_id) keep (dense_rank first order by rn.datecreated)
from referencenumbers rn
where rn.person_id = people.id )
from people
where people.age > 18;