我在Oracle数据库上执行查询。让我们说我有一张桌子,人。每个人可以有多个参考号。参考编号存储在不同的表REFERENCENUMBERS中。
REFERENCENUMBERS包含一列PERSON_ID,它与PEOPLE表的ID列相同。通过此ID可以将表连接起来。
我想说我想在PEOPLE表上执行查询。但是我只希望每个人记录返回一个参考号:即如果一个人有多个参考号,我不希望每个参考号每人返回多行。
我选择了一个如何只选择一个参考号的标准:最早创建的参考号。创建参考号的日期作为DATECREATED存储在REFERENCENUMBERS表中。
以下代码完成此任务:
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子句而包含子子查询似乎很麻烦。
必须有一种更简单,更清洁的方法。有什么建议吗?
(顺便说一下 - 示例代码与我实际工作的内容大大简化。请不要提供能够以不同风格的JOIN等方式实质性修改我的主查询的答案 - 谢谢)。< / p>
答案 0 :(得分:2)
最简单的是前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;
More details here(需要Oracle 12.1或更高版本。)
或者这个(适用于早期版本):
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;
(为了便于阅读,我给了referencenumbers
一个较短的别名。)
答案 1 :(得分:1)
试试这个
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