我有一个具有以下结构的查询:
SELECT
PEOPLE.ID,
(
SELECT MIN(R.VALUE) KEEP (DENSE_RANK FIRST ORDER BY R.DATE_OF_CREATION)
FROM REFERENCE_NUMBERS R
WHERE
R.DELETED IS NULL
AND R.PERSON_ID(+) = PEOPLE.ID
) AS PRIMARY_REFERENCE_NUMBER,
PEOPLE.NAME,
PEOPLE.DATE_OF_BIRTH
FROM
PEOPLE
WHERE
PEOPLE.DELETED IS NULL
AND PEOPLE.DATE_OF_BIRTH > TO_DATE('2000-01-01','yyyy-mm-dd')
这一点是,一个人可以有多个参考号:但是我只想为每个人返回一个参考号,而不是多行。因此,我选择了最早创建的具有最小值的参考。我使用主SELECT子句中的子查询来执行此操作。上面的代码有效。
我想看看是否可以将其移至主要查询的一部分。从逻辑上讲,我本以为应该这样:
SELECT
PEOPLE.ID,
MIN(R.VALUE) KEEP (DENSE_RANK FIRST ORDER BY R.DATE_OF_CREATION),
PEOPLE.NAME,
PEOPLE.DATE_OF_BIRTH
FROM
PEOPLE,
REFERENCE_NUMBERS R
WHERE
PEOPLE.DELETED IS NULL
AND PEOPLE.DATE_OF_BIRTH > TO_DATE('2000-01-01','yyyy-mm-dd')
AND R.DELETED IS NULL
AND R.PERSON_ID(+) = PEOPLE.ID
但是我得到了错误:ORA-00937: not a single-group function
根据https://www.techonthenet.com/oracle/errors/ora00937.php-我需要在主查询中使用GROUP BY语句。但是,如果我添加以下行:
GROUP BY R.VALUE
...然后我得到错误ORA-00979: not a GROUP BY expression
我觉得我快到了,但是只需要一些额外的指导即可。有人可以帮忙吗?
注意:我完全了解“新”样式的JOIN语法,并且人们倾向于建议使用此语法。但是我使用“旧式”联接是有原因的。以上只是一个最小的可验证示例。我的真实代码要复杂得多,涉及到以复杂方式连接的多个表-当涉及到这种复杂程度时,旧语法更容易理解。请尽可能提供老式语法的答案。
答案 0 :(得分:0)
在您的SELECT
子句中没有反对使用该子查询的内容。如果要将其移至FROM
子句,请按person_id
分组,以便每人获得一行,并对没有参考编号的人使用外部联接。
SELECT
p.id,
r.primary_reference_number,
p.name,
p.date_of_birth
FROM people p
LEFT JOIN
(
SELECT person_id, MIN(value) KEEP (DENSE_RANK FIRST ORDER BY date_of_creation)
AS primary_reference_number
FROM reference_numbers
WHERE deleted IS NULL
GROUP BY person_id
) r ON r.person_id = p.id
WHERE p.deleted is null
AND p.date_of_birth > date '2000-01-01;
您可以将每个人与其所有参考文献一起加入,然后汇总整个混乱情况。这会使查询看起来更简单,但是我不喜欢这种方法。您需要每人一个参考号,因此请为每个人添加一个参考号。
无论如何,这将是编写此类查询的方式:
SELECT
p.id,
MIN(r.value) KEEP (DENSE_RANK FIRST ORDER BY r.date_of_creation)
AS primary_reference_number,
p.name,
p.date_of_birth
FROM people p
LEFT JOIN reference_numbers r ON r.person_id = p.id AND r.deleted IS NULL
WHERE p.deleted is null
AND p.date_of_birth > date '2000-01-01
GROUP BY p.id, p.name, p.date_of_birth;
Oracle强制您命名在GROUP BY
子句中选择的所有非聚合列。根据SQL标准,您仅需要people.id
,因为其他列在功能上都依赖于它,但是不幸的是,Oracle没有此功能。
答案 1 :(得分:0)
查询中的第二列与其他列不同步,同样按其他列分组可能会帮助您
SELECT
PEOPLE.ID,
MIN(R.VALUE) KEEP (DENSE_RANK
FIRST ORDER BY
R.DATE_OF_CREATION),
PEOPLE.NAME,
PEOPLE.DATE_OF_BIRTH
FROM
PEOPLE P,
REFERENCE_NUMBERS R
WHERE
PEOPLE.DELETED IS NULL
AND PEOPLE.DATE_OF_BIRTH >
TO_DATE('2000-01-01','yyyy-mm-dd')
AND R.DELETED IS NULL
AND R.PERSON_ID(+) = PEOPLE.ID
GROUP BY
P.ID, P.NAME, P.DATE_OF_BIRTH