2013-02-20 41 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