简体   繁体   中英

Subquery in FROM clause fails in MySQL

I stumbled upon a strange behavior of MySQL (v.8) when trying to run a nested subquery in the FROM clause. The (relevant part of the) schema of the sample database I am using is as follows:

在此处输入图片说明

The following two queries run identically on SQL Server:

SELECT SUM(tot) as total
 FROM (
     SELECT 
        SUM(OD.quantityOrdered * OD.priceEach) as tot,
        C.customerNumber
     FROM customers C
     INNER JOIN orders O ON C.customerNumber = O.customerNumber
     INNER JOIN orderdetails OD ON O.orderNumber = OD.orderNumber
     GROUP BY O.orderNumber, C.customerNumber
) AS CO
GROUP BY CO.customerNumber;

and

SELECT 
  (
    SELECT SUM(tot) as total
    FROM 
        (
            SELECT 
                (
                    SELECT  SUM(OD.quantityOrdered * OD.priceEach)
                    FROM orderdetails OD 
                    WHERE OD.orderNumber = O.orderNumber
                ) AS tot
            FROM orders O
            WHERE O.customerNumber = C.customerNumber
        ) AS ORD
  ) AS total
FROM customers AS C;

However, on MySQL, the first one runs fine, while the second one results in an error:

Error Code: 1054. Unknown column 'C.customerNumber' in 'where clause'

I will appreciate any clues about why this is happening. Please note that I am mostly interested not in workarounds or other ways to implement this query, but in understanding the reasons why the nested query fails.

C table alias in not in scope for the suquery
try refactoring the query using a join

eg

select  c.customerNumber,  t.my_tot 
FROM customers AS C
INNER JOIN (

  SELECT  O.customerNumber, SUM(OD.quantityOrdered * OD.priceEach) my_tot
  FROM orderdetails OD 
  INNER JOIN orders O ON  OD.orderNumber = O.orderNumber
  GROUP BY O.customerNumber
) t on t.customerNumber = c.customerNumber

or

select  t.my_tot 
FROM customers AS C
INNER JOIN (

  SELECT  O.customerNumber, SUM(OD.quantityOrdered * OD.priceEach) my_tot
  FROM orderdetails OD 
  INNER JOIN orders O ON  OD.orderNumber = O.orderNumber
  GROUP BY O.customerNumber
) t on t.customerNumber = c.customerNumber

you can try like below

SELECT 
  (   
      select SUM(tot) as total from

          (   
            SELECT 
                (
                    SELECT  SUM(OD.quantityOrdered * OD.priceEach)
                    FROM orderdetails OD 
                    WHERE OD.orderNumber = O.orderNumber
                ) AS tot,customerNumber
            FROM orders O
           )  as ord      
            WHERE ord.customerNumber = C.customerNumber        
  ) AS total
FROM customers AS C;

Your customers table not in scope of subquery where you used in where condition WHERE O.customerNumber = C.customerNumber so i made alias of that and then later level i used same condition where customers table has scope

You have a correlated subquery in the second case. However, the correlation clause is two levels deep .

Many databases will still recognize c , even when nested multiple levels. However, MySQL (and Oracle and I think MS Access) is a database that limits correlation clauses to one level deep.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM