簡體   English   中英

MySQL:在引用外部表的列時,在JOIN的子查詢中使用WHERE子句會產生錯誤

[英]MySQL: Using WHERE clause in subquery in JOIN gives error when outer table's column is referenced

我正在嘗試使用子查詢使用JOIN查詢幾個表來縮小返回結果的范圍。 當我在子查詢中使用WHERE子句引用外部查詢中的列值時,在where子句中出現錯誤#1054未知列。

我想用mode = 2查詢主表,並從Transaction表中獲取相關記錄。 如果Master.mode = 2和Master.type = 1,則獲取所有ID匹配但type = 2的交易,反之亦然。 簡而言之,從ID匹配但類型值相反的Transaction中獲取記錄。 如果記錄多於1條,則從“事務”表中獲取“金額”最高的記錄。

Master table
+----+-----+-------+-------+
|id  |mode |type   |other  |
+----+-----+-------+-------+
|1   |1    |1      |11111  |
|2   |2    |2      |22222  |
|3   |2    |1      |33333  |
|4   |1    |2      |44444  |
+----+-----+-------+-------+

Transaction table
+----+-------+-------+
|id  |type   |amount |
+----+-------+-------+
|1   |1      |1000   |
|1   |2      |1000   |
|2   |1      |2000   |
|2   |2      |3000   |
|3   |1      |500    |
|3   |1      |5000   |
|3   |1      |3000   |
|3   |2      |4000   |
|3   |2      |2000   |
|4   |1      |1000   |
|4   |2      |2000   |
|1   |1      |3000   |
+----+-------+-------+

Expected Result
+----+-----+-------+-------+-------+
|id  |mode |type   |other  |amount |
+----+-----+-------+-------+-------+
|2   |2    |2      |22222  |2000   |
|3   |2    |1      |33333  |4000   |
+----+-----+-------+-------+-------+

My query
SELECT t1.*, t2.Amount
FROM master AS t1
    INNER JOIN (
            SELECT t3.*
                FROM transactions AS t3
                WHERE t3.id=t1.id AND t3.Type=(CASE WHEN t1.Type=1 THEN 2 ELSE 1 END)
                ORDER BY t3.Amount DESC
                LIMIT 1
        ) AS t2 ON t1.id=t2.id
WHERE t1.Mode=2 AND t2.Type=(CASE WHEN t1.Type=1 THEN 2 ELSE 1 END)

我收到錯誤#1054-'where子句'中的未知列't1.id'

達到預期的效果。 我們可以從這樣的查詢開始:

 SELECT m.id
      , m.mode
      , m.type
      , m.other
   FROM master m
  WHERE m.mode = 2
  ORDER BY ...

對於該查詢返回的每一行,我們似乎都希望獲得一個值。 我們可以使用相關子查詢來獲取值,例如:

 SELECT t.amount
   FROM transactions t
  WHERE t.id   = m.id 
    AND t.type = IF(m.type=2,1,2)
  ORDER BY t.amount DESC
  LIMIT 1

相關子查詢返回一列,並且返回不超過一行,因此我們可以將其包括在原始查詢的SELECT列表中。

像這樣:

 SELECT m.id
      , m.mode
      , m.type
      , m.other
      , ( SELECT t.amount
            FROM transactions t
           WHERE t.id   = m.id 
             AND t.type = IF(m.type=2,1,2)
           ORDER BY t.amount DESC
           LIMIT 1
        ) AS `Amount`
   FROM master m
  WHERE m.mode = 2 
  ORDER BY ... 

這種工作方式是執行外部查詢(來自主服務器的查詢)。 對於返回的每一行,都會評估SELECT列表中的表達式。 評估像m.idm.modem.type這樣的表達式非常簡單,每個表達式都返回一個標量值,該值將放入結果集中。

評估相關子查詢的工作方式相同。 稍微復雜一點……MySQL使用當前m行的值執行子查詢,並返回單個值,該值被放入結果集中。

注意:

如果相關子查詢不返回任何行,則將NULL放入結果集中。

如果規范僅返回在數量列中具有非NULL值的行,則可以添加HAVING子句

 WHERE m.mode = 2 
HAVING `Amount` IS NOT NULL
 ORDER BY ... 

另請注意:

因為相關的子查詢是針對外部查詢返回的每一行執行的,所以對於主行中的很多行,多數民眾贊成在很多子查詢中執行,這會降低大型集合的性能。

這使得為​​子查詢提供合適的索引非常重要。 理想情況下,覆蓋指數...

ON transaction (id, type, amount)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM