簡體   English   中英

SELECT中的子查詢:嘗試移至主查詢

[英]Subquery in SELECT: trying to move to main query

我有以下結構的查詢:

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語法,並且人們傾向於建議使用此語法。 但是我使用“舊式”聯接是有原因的。 以上只是一個最小的可驗證示例。 我的真實代碼要復雜得多,涉及到以復雜方式連接的多個表-當涉及到這種復雜程度時,舊語法更容易理解。 請盡可能提供老式語法的答案。

沒有什么反對在您的SELECT子句中有該子查詢。 如果要將其移至FROM子句,請按person_id ,以便每人獲得一行,並對沒有參考號的人使用外部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沒有此功能。

查詢中的第二列與其他列不同步,按其他列分組可能會如下所示

      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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM