接受的答案確實提供了一個工作解決方案,但是爲什麼現有查詢不能像寫入那樣正確解釋。
存在多種類型的子查詢,返回多種類型的結果。
在您的查詢:
WHERE expr IN ((/* subq 1 */), (/* subq 2 */), (/* subq 3 */))
...等價於...
WHERE expr = (/* subq 1 */)
OR expr = (/* subq 2 */)
OR expr = (/* subq 3 */)
這是,也只能是三相等比較。以這種方式使用子查詢將一定可以在標量上下文...解釋和標量子查詢只能返回一行或零行,因爲子查詢的結果將被用作scalar operand。對於服務器來解釋它否則是不合邏輯的:你能比較一個值與兩個值還是更多,並進行相等比較?如果您的查詢不是,請求服務器從子查詢中構建所有結果的集合,然後測試OWNER.ID是否設置爲IN()
。您的查詢要求服務器構建一個包含最多三個標量值(每個子查詢一個)的集合,並確定OWNER.ID是否爲IN()
即(可能小得多)集合。這些子查詢中的任何一個返回多於一行的事實使查詢無效。你很幸運,它已經不起作用了。如果您選擇的數據只匹配一行,現在就可以奏效,但是當您有更多的匹配項時,這些數據就會分崩離析。
ERROR 1242 (21000): Subquery returns more than 1 row
如果(人工)加入LIMIT 1
到三個子查詢中,你會發現,該查詢實際上做的工作,這說明我的觀點。結果將不完整,但查詢是有效的,這反駁了錯誤是關於「列」的斷言。這是一組......但是,正如所寫,它是,而且只能是一組標量。
重構與UNION
澄清你的意圖到服務器。
注意,如果斷言誤差約爲列是正確的,該消息會有所不同:
ERROR 1241 (21000): Operand should contain 1 column(s)
現在,已經解釋了錯誤的實際原因,我也會扔在一個備用解。如果您尚未擁有VISITOR和BOARDING中的(OWNER_ID),您應該有一個索引。此解決方案與UNION
解決方案之間的性能可能會因各種表中的數據組成以及MySQL服務器的版本而異。這兩種解決方案都不是最佳選擇,因爲LIKE
比較中的起始%
需要表或至少一個包含該列的索引(如果有的話)被完整讀取。這是全表掃描或全索引掃描,「掃描」是指逐行。結局%
沒問題;開始%
是昂貴的,因爲它從列的左手邊取消固定模式,這是索引工作的地方。如果可以的話,應用程序允許的情況下將其刪除,以獲得更好的性能,並對搜索列進行索引;如果你不能刪除領先的%
,至少要明白這是你將會看到的性能的貢獻者。這是B-Tree索引的一般限制,而不是MySQL。你最終也可能想看看FULLTEXT
search。
SELECT o.*
FROM OWNER o
WHERE o.LAST_NAME LIKE '%pickles%'
OR o.FIRST_NAME LIKE '%pickles%'
OR EXISTS(SELECT *
FROM VISITOR v
WHERE v.OWNER_ID = o.ID
AND (v.NAME LIKE '%pickles%' OR v.SIZE LIKE '%pickles%')
)
OR EXISTS(SELECT *
FROM BOARDING b
WHERE b.OWNER_ID = o.ID
AND (COMMENTS LIKE '%pickles%' OR PERSONAL_BELONGINGS LIKE '%pickles%')
);
請注意,EXISTS(SELECT * ...)
是yet another form of subquery, entirely different than anything we've considered so far。特別值得注意的是*
只是一個慣例。您可以說SELECT 1
或SELECT TRUE
,並沒有關係,因爲沒有數據實際上被選中,並且EXISTS()
沒有任何數據被返回,TRUE
除外 - 子查詢匹配目標表中的一行或更多行 - 或FALSE
- 它沒有。請注意,這些查詢引用外部查詢o.ID中的值,因此它們在此處我們檢查所有者表以查找匹配條件,然後在必要時檢查行中是否存在行訪客或登機以獲得匹配標準。如果名爲「Cat」的女性有一隻名爲「Cat」的狗,並且您在尋找「Cat」,那麼我們會在OWNER中找到它,優化程序可能會避免爲該用戶搜索其他兩張表,因爲我們已經知道她是一場比賽,無論出於何種原因。
參見:https://dev.mysql.com/doc/refman/5.6/en/subquery-errors.html
非常感謝您@Raging公牛。 我認爲個人選擇將結合身份證。 爲什麼多個ID會被視爲錯誤? 它試圖說它發現重複? – Kreeverp
@Kreeverp:當您使用'IN'運算符時,子查詢必須只返回1列來查找。使用您的查詢,它將返回3列。這就是錯誤所說的。子查詢返回的值超過1意味着「超過1列」。 –
有點令人困惑,錯誤報告「行」而不是列? – Kreeverp