2013-02-20 72 views
1

Gahh ..令我沮喪。教科書要求我們重寫下面的語句而不使用共同相關的子查詢。Co-Related SubQuery

SELECT DISTINCT V.VENDOR_NAME, I.INVOICE_NUMBER, I.INVOICE_DATE, I.INVOICE_TOTAL 
FROM VENDORS V 
JOIN INVOICES I 
    ON V.VENDOR_ID = I.VENDOR_ID 
WHERE I.INVOICE_DATE IN 
    (SELECT MIN(INVOICE_DATE) FROM INVOICES IV WHERE IV.VENDOR_ID = V.VENDOR_ID) 
AND I.INVOICE_NUMBER IN 
    (SELECT MIN(INVOICE_NUMBER) FROM INVOICES IV WHERE IV.VENDOR_ID = V.VENDOR_ID) 
ORDER BY V.VENDOR_NAME 

我該怎麼做?我想不出反正它重新寫無子查詢:S

+3

有點奇怪的查詢,如果'INVOICE_DATE'和'INVOICE_NUMBER'不是它們的同一發票的最小值,它根本不會顯示任何結果。 – 2013-02-20 17:49:23

+0

我想知道爲什麼教科書對此查詢有DISTINCT。這有點代碼味道,他們沒有在涉及的表格上設置正確的唯一性約束,或者沒有仔細檢查。 – 2013-02-21 03:28:21

回答

2

你可以把它寫成一個簡單的LEFT JOIN根本不需要做任何的子查詢;

SELECT DISTINCT V.VENDOR_NAME, I.INVOICE_NUMBER, I.INVOICE_DATE, I.INVOICE_TOTAL 
FROM VENDORS V 
JOIN INVOICES I 
    ON V.VENDOR_ID = I.VENDOR_ID 
LEFT JOIN INVOICES I2 
    ON V.VENDOR_ID = I2.VENDOR_ID 
    AND (I2.INVOICE_NUMBER < I.INVOICE_NUMBER OR 
     I2.INVOICE_DATE < I.INVOICE_DATE) 
WHERE I2.INVOICE_NUMBER IS NULL; 

An SQLfiddle to test with

+0

:O我從來沒有想過這是可能的..這個解決方案的作品!我現在必須研究這個解決方案。找出爲什麼LeftJoin替換子查詢。 – Brandon 2013-02-20 22:20:15

+0

+1相關子查詢與左連接有效地執行相同的工作(只要第一個表中的每條記錄的相關結果不超過1條記錄),所以它們通常可以輕微地重寫爲左連接。 – 2013-02-21 03:26:27

1

試試這個:

SELECT 
    DISTINCT V.VENDOR_NAME, 
    I.INVOICE_NUMBER, 
    I.INVOICE_DATE, 
    I.INVOICE_TOTAL 
FROM VENDORS V 
    JOIN INVOICES I 
     ON V.VENDOR_ID = I.VENDOR_ID 
    JOIN 
    (
     SELECT 
      VENDOR_ID, 
      MIN(INVOICE_DATE) MIN_INVOICE_DATE, 
      MIN(INVOICE_NUMBER) MIN_INVOICE_NUMBER 
     FROM INVOICES 
     GROUP BY VENDOR_ID 
    ) MV 
    ON V.VENDOR_ID = MV.VENDOR_ID 
     AND I.INVOICE_DATE= MV.MIN_INVOICE_DATE 
     AND I.INVOICE_NUMBER = MV.MIN_INVOICE_NUMBER 
ORDER BY V.VENDOR_NAME