[英]Strange Doctrine behaviour with double innerJoin()
我有這樣的數據庫模式:我的數據庫模式: http : //i.stack.imgur.com/vFKRk.png
解釋上下文:一個用戶寫一條消息。 他可以將其發送給一個或多個用戶。
我成功地獲得了一個用戶的作者的消息標題。 然而,我用於此項目的Doctrine使用2個查詢來完成它。 這對我來說有點奇怪,我希望了解,為什么。 通常,我們可以使用一個SQL查詢來完成。
我的DQL查詢:
$q = Doctrine_Query::create()->select('id_me, users_id_us, state_me, type_me, mc.title_mc, us.login_us') ->from('messages m')->innerJoin('m.messages_content mc')->innerJoin('mc.Users us') ->where('users_id_us = ?', $user)->limit($opt['limit'])->offset($opt['offset'])->orderBy($opt['order']);return $q->fetchArray();
Doctrine返回的SQL查詢:
SELECT DISTINCT m3.id_me FROM messages m3 INNER JOIN messages_content m4 ON m3.messages_content_id_mc = m4.id_mc INNER JOIN users u2 ON m4.users_id_us = u2.id_us WHERE m3.users_id_us = '6' ORDER BY m3.id_me DESC LIMIT 2
SELECT m.id_me AS m__id_me, m.users_id_us AS m__users_id_us, m.state_me AS m__state_me, m.type_me AS m__type_me, m2.id_mc AS m2__id_mc, m2.title_mc AS m2__title_mc, u.id_us AS u__id_us, u.login_us AS u__login_us FROM messages m INNER JOIN messages_content m2 ON m.messages_content_id_mc = m2.id_mc INNER JOIN users u ON m2.users_id_us = u.id_us WHERE m.id_me IN ('11') AND (m.users_id_us = '6') ORDER BY m.id_me DESC
為什么我的Doctrine查詢不會像這樣返回查詢:
SELECT m.id_me, m.users_id_us, m.state_me, m.type_me, mc.title_mc, u.login_us FROM messages m JOIN messages_content mc ON mc.id_mc = m.messages_content_id_mc JOIN users u ON u.id_us = mc.users_id_us WHERE m.users_id_us = 6;
有沒有想過轉換我的DQL查詢並執行一次?
這與LIMIT
部分有關。 :) Doctrine LIMIT與MySQL限制有點不同。
MySQL LIMIT只發出查詢,並在找到與您的SQL查詢匹配的n
行后立即停止搜索。 由於在ORM中,這確實是意外行為(很可能是在標量布局中,SQL SELECT * FROM myModel LEFT JOIN someOtherModel ON someCondition LIMIT 3
實際上僅返回一個myModel
實例,而不是三個,因為SELECT * FROM myModel LEFT JOIN someOtherModel ON someCondition LIMIT 3
可以導致3行。
如果您的DQL查詢是FROM school s INNER JOIN s.students LIMIT 15
,它意味着:給我的15個實例school
有至少一個student
相關的(因此INNER JOIN
),及其所有的student
同伙。 要做到這一點,Doctrine首先要求DISTINCT school
使用完全相同的查詢參數和LIMIT
部分,以確定應該返回哪15個學校ID。 完成此操作后,接下來將查詢這些ID,而不使用LIMIT部分。
如果你沒有實際的問題,huzzah,找到上述這種行為的解釋。 如果您的查詢輸出不是您預期的,請確保將這些步驟納入考慮范圍。 例如,如果您的DQL是FROM school s INNER JOIN s.students LIMIT 15
,並且您想知道為什么您有超過15名學生,請嘗試: FROM students s INNER JOIN s.school LIMIT 15
。 在MySQL中,這意味着基本相同(忽略結果的順序),但在Doctrine中,這意味着您將獲得15 students
而不是15 schools
。
這對於一些更復雜的查詢也很困擾。 我發現的唯一解決方案是完全繞過愚蠢:
$q = Doctrine_Manager::getInstance()->getCurrentConnection();
$my_result = $q->fetchAssoc(" ... PUT SQL HERE ... ");
有效的解決方案:
我更改了關系別名,並指定了messages_content和users之間參與ON聯合的列。
正確的Doctrine查詢是:
$q = Doctrine_Query::create()
->select('id_me, users_id_us, state_me, type_me, mc.title_mc, us.login_us')
->from('messages m')
->innerJoin('m.messages_content mc')
->innerJoin('m.Users us ON mc.users_id_us=us.id_us')
->where('users_id_us = ?', $user)
->limit($opt['limit'])
->offset($opt['offset'])
->orderBy($opt['order']);
它提供了這樣的SQL查詢:
SELECT m.id_me AS m__id_me, m.users_id_us AS m__users_id_us, m.state_me AS m__state_me, m.type_me AS m__type_me, m2.id_mc AS m2__id_mc, m2.title_mc AS m2__title_mc, u.id_us AS u__id_us, u.login_us AS u__login_us FROM messages m INNER JOIN messages_content m2 ON m.messages_content_id_mc = m2.id_mc INNER JOIN users u ON (m2.users_id_us = u.id_us) WHERE (m.users_id_us = '7') ORDER BY m.id_me DESC LIMIT 2
Tom和Pelle ten Cate,感謝您的參與。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.