2017-06-22 66 views
3

我有一個查詢,在我們的Firebird SQL數據模塊工作。火鳥到MySQL查詢遷移 - 選擇內部加入子查詢

我們遷移到MySQL和我的所有查詢工作沒有問題,除了這一個。

請幫我解決這個問題。我得到一個錯誤:

Failed to Execute. Unknown column 'part.id' in 'on clause'

我火鳥查詢:

SELECT vendor.name AS "Vendor Name", 
    Cast(Cast(vendorparts.lastdate AS date) AS CHAR(10)) AS "Last Date", 
    CASE product.price 
    WHEN '0' THEN 'CONFIRM' 
    WHEN NULL THEN 'CONFIRM' 
    ELSE Round(product.price, 2) 
    end AS "D-Price", 
    Cast(vendorparts.lastcost AS DECIMAL(18, 2)) AS "Last Cost", 
    Cast(lowestcost.lowestcost AS DECIMAL(18, 2)) AS "Lowest Cost", 
    Cast(highestcost.highestcost AS DECIMAL(18, 2)) AS "Highest Cost", 
    part.num AS "Part Number", 
    part.description AS "Part Description" 

FROM vendor, 
     vendorparts, 
     part, 
     product 
     INNER JOIN (SELECT vendorparts.partid, 
          Max(vendorparts.lastcost) AS Highestcost 
        FROM vendorparts 
        GROUP BY vendorparts.partid) AS highestcost 
       ON part.id = highestcost.partid 
     INNER JOIN (SELECT vendorparts.partid, 
          Min(vendorparts.lastcost) AS Lowestcost 
        FROM vendorparts 
        GROUP BY vendorparts.partid) AS lowestcost 
       ON part.id = lowestcost.partid 
WHERE vendor.id = vendorparts.vendorid 
     AND product.partid = part.id 
     AND vendorparts.partid = part.id 
     AND vendorparts.lastcost <> 0 

所有表都在數據庫中,除了這是在子查詢創建lowestcosthighestcost

希望我的要求清楚寫出來。但總結一下 - 我需要將這個可行的Firebird查詢遷移到MySQL中。

爲什麼這個工作在火鳥但不是MySQL?

+1

不要混合使用逗號連接語法和內部連接語法.. –

+0

我可以問你爲什麼遷移到MySQL? – skafinski

+1

@skafinski我們的庫存管理系統剛剛在昨天更新爲新版本。整個系統從Firebird SQL遷移到MySQL。到目前爲止,性能提高得多,查詢編譯速度更快。 –

回答

4

的問題是,在MySQL中comma operator has lower precedencejoin操作者,因此product inner join (subquery) on part.id = highestcost.partid inner join (subquery) on part.id = lowestcost.partid連接被評價part表在表達接合,因此,該錯誤消息。

更換逗號運營商簡單join運營商和移動加入從where子句條件on條款和所有將被罰款:

... 
FROM vendor 
     inner join vendorparts on vendor.id = vendorparts.vendorid 
     inner join part on vendorparts.partid = part.id 
     inner join product on product.partid = part.id 
     INNER JOIN (SELECT vendorparts.partid, 
          Max(vendorparts.lastcost) AS Highestcost 
        FROM vendorparts 
        GROUP BY vendorparts.partid) AS highestcost 
       ON part.id = highestcost.partid 
     INNER JOIN (SELECT vendorparts.partid, 
          Min(vendorparts.lastcost) AS Lowestcost 
        FROM vendorparts 
        GROUP BY vendorparts.partid) AS lowestcost 
       ON part.id = lowestcost.partid 
WHERE vendorparts.lastcost <> 0 

如果你有,你混逗號操作和明確的更多此類查詢那麼你應該檢查它們,因爲即使MySQL中沒有語法錯誤,它們也可能產生不同的結果。

+0

謝謝你的影子。這是第一個答案,並馬上工作。簡單的解釋。 –

+0

在Firebird中混合顯式(SQL-92)和隱式(SQL-89)連接也被認爲是不好的樣式,這已知會導致意想不到的效果甚至是錯誤。即使對於最初的Firebird數據庫,這些查詢也可以被重新修改 –

1

此查詢在Firebird 3.0及更高版本中也不起作用(請參閱Support for Mixed-Syntax Joins is Gone)。原因是你正在將SQL-89風格的聯接與SQL-92風格的聯接相結合。

你需要重寫使用顯式查詢連接無處不在,所以:

... 
FROM vendor 
    inner join vendorparts on vendor.id = vendorparts.vendorid 
    inner join part on vendorparts.partid = part.id 
    inner join product on product.partid = part.id 
    INNER JOIN (SELECT vendorparts.partid, 
         Max(vendorparts.lastcost) AS Highestcost 
       FROM vendorparts 
       GROUP BY vendorparts.partid) AS highestcost 
      ON part.id = highestcost.partid 
    INNER JOIN (SELECT vendorparts.partid, 
         Min(vendorparts.lastcost) AS Lowestcost 
       FROM vendorparts 
       GROUP BY vendorparts.partid) AS lowestcost 
      ON part.id = lowestcost.partid 
WHERE vendorparts.lastcost <> 0 
1

請勿混用顯性和隱性的加入
避免在列名和表名使用相同的別名(此示例中AI是指t1和t2) ,避免AS的子查詢的表名

SELECT 
    vendor.name AS "Vendor Name", 
    Cast(Cast(vendorparts.lastdate AS date) AS CHAR(10)) AS "Last Date", 
    CASE product.price 
    WHEN '0' THEN 'CONFIRM' 
    WHEN NULL THEN 'CONFIRM' 
    ELSE Round(product.price, 2) 
    end AS "D-Price", 
    Cast(vendorparts.lastcost AS DECIMAL(18, 2)) AS "Last Cost", 
    Cast(lowestcost.lowestcost AS DECIMAL(18, 2)) AS "Lowest Cost", 
    Cast(highestcost.highestcost AS DECIMAL(18, 2)) AS "Highest Cost", 
    part.num AS "Part Number", 
    part.description AS "Part Description" 

FROM vendor 
INNER JOIN vendorparts on vendor.id = vendorparts.vendorid AND vendorparts.lastcost <> 0 
INNER JOIN part on vendorparts.partid = part.id and 
INNER JOIN product on product.partid = part.id 
INNER JOIN (SELECT vendorparts.partid, 
          Max(vendorparts.lastcost) AS Highestcost 
        FROM vendorparts 
        GROUP BY vendorparts.partid) t1 
       ON part.id = t1.partid 
INNER JOIN (SELECT vendorparts.partid, 
          Min(vendorparts.lastcost) AS Lowestcost 
        FROM vendorparts 
        GROUP BY vendorparts.partid) t2 
       ON part.id = t2.partid