![](/img/trans.png)
[英]Why does this :id in Rails not work with Postgresql but it does work with MySQL?
[英]Rails: Why does where(id: objects) work?
我有以下聲明:
Customer.where(city_id: cities)
這導致以下SQL語句:
SELECT customers.* FROM customers WHERE customers.city_id IN (SELECT cities.id FROM cities...
這是預期的行為嗎? 它在某處記錄了嗎? 我不會使用上面的Rails代碼,而是使用以下之一:
Customer.where(city_id: cities.pluck(:id))
要么
Customer.where(city: cities)
這導致完全相同的SQL語句。
AREL查詢庫允許您將ActiveRecord對象作為快捷方式傳遞。 然后它會將其主鍵屬性傳遞給它用於聯系數據庫的SQL。
在查找多個對象時,AREL庫將嘗試在盡可能少的數據庫往返中查找信息。 它通過將您正在進行的查詢作為一組條件來執行此操作,直到檢索對象為止。
這種方式效率低下:
users = User.where(age: 30).all
# ^^^ get all these users from the database
memberships = Membership.where(user_id: users)
# ^^^^^ This will pass in each of the ids as a condition
基本上,這種方式會發出兩個SQL語句:
select * from users where age = 30;
select * from memberships where user_id in (1, 2, 3);
其中每個都涉及在應用程序和數據之間的網絡端口上調用,然后通過同一端口傳回。
這會更有效:
users = User.where(age: 30)
# This is still a query object, it hasn't asked the database for the users yet.
memberships = Membership.where(user_id: users)
# Note: this line is the same, but users is an AREL query, not an array of users
它將構建一個單獨的嵌套查詢,因此它只需要對數據庫進行一次往返。
select * from memberships
where user_id in (
select id from users where age = 30
);
所以,是的,這是預期的行為。 它有點像Rails魔術,它旨在提高您的應用程序的性能,而無需了解它的工作原理。
還有一些很酷的優化,比如你first
撥打或last
而不是all
,它只會檢索一條記錄。
User.where(name: 'bob').all
# SELECT "USERS".* FROM "USERS" WHERE "USERS"."NAME" = 'bob'
User.where(name: 'bob').first
# SELECT "USERS".* FROM "USERS" WHERE "USERS"."NAME" = 'bob' AND ROWNUM <= 1
或者,如果您設置了一個訂單,然后調用最后一個,它將反轉訂單,然后只獲取列表中的最后一個(而不是抓取所有記錄,只給出最后一個記錄)。
User.where(name: 'bob').order(:login).first
# SELECT * FROM (SELECT "USERS".* FROM "USERS" WHERE "USERS"."NAME" = 'bob' ORDER BY login) WHERE ROWNUM <= 1
User.where(name: 'bob').order(:login).first
# SELECT * FROM (SELECT "USERS".* FROM "USERS" WHERE "USERS"."NAME" = 'bob' ORDER BY login DESC) WHERE ROWNUM <= 1
# Notice, login DESC
它為什么有效?
ActiveRecord查詢構建器中的某些內容非常智能,可以看到如果傳遞數組或查詢/條件,則需要構建IN
子句。
這記錄在哪里?
是的, http://guides.rubyonrails.org/active_record_querying.html#hash-conditions
如果要使用IN表達式查找記錄,可以將數組傳遞給條件哈希:
Client.where(orders_count: [1,3,5])
此代碼將生成如下SQL:
SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.