Firebird到MySQL查询迁移 - 选择内部连接子查询

时间:2017-06-22 14:41:17

标签: mysql select join nested firebird

我的Firebird SQL数据模块中有一个查询。

我们迁移到MySQL,除了这个,我的所有查询都没有问题。

请帮我解决这个问题。我收到一个错误:

  

执行失败。未知栏' part.id'在' on条款'

我的Firebird查询:

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中工作。

为什么这会在Firebird中运行而不是MySQL?

3 个答案:

答案 0 :(得分:4)

问题是在mySQL中comma operator has lower precedence而不是join运算符,因此product inner join (subquery) on part.id = highestcost.partid inner join (subquery) on part.id = lowestcost.partid联接在<{strong> 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中没有语法错误。

答案 1 :(得分: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 

答案 2 :(得分: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