【发布时间】:2009-09-06 12:32:02
【问题描述】:
让我们假设三个模型,标准连接:
class Mailbox < ActiveRecord::Base
has_many :addresses
has_many :domains, :through => :addresses
end
class Address < ActiveRecord::Base
belongs_to :mailbox
belongs_to :domain
end
class Domain < ActiveRecord::Base
has_many :addresses
has_many :mailboxes, :through => :addresses
end
现在显然,如果您想知道任何给定邮箱的地址在哪些域中,您有两种可能的方法:
m = Mailbox.first
# either: SELECT DISTINCT domains.id, domains.name FROM "domains" INNER JOIN
# "addresses" ON "domains".id = "addresses".domain_id WHERE
# (("addresses".mailbox_id = 1))
m.domains.all(:select => 'DISTINCT domains.id, domains.name')
# or: SELECT domains.id, domains.name FROM "domains" INNER JOIN "addresses" ON
# "domains".id = "addresses".domain_id WHERE (("addresses".mailbox_id = 1))
# GROUP BY domains.id, domains.name
m.domains.all(:select => 'domains.id, domains.name',
:group => 'domains.id, domains.name')
对我来说,问题是我不知道哪种解决方案更好。当我不指定任何其他条件时,PostgreSQL 查询规划器倾向于第二个解决方案(按预期工作),但如果我向查询添加条件,则归结为“唯一”与“组”:
使用“DISTINCT”:
Unique (cost=16.56..16.57 rows=1 width=150)
-> Sort (cost=16.56..16.56 rows=1 width=150)
Sort Key: domains.name, domains.id
-> Nested Loop (cost=0.00..16.55 rows=1 width=150)
-> Index Scan using index_addresses_on_mailbox_id on addresses (cost=0.00..8.27 rows=1 width=4)
Index Cond: (mailbox_id = 1)
-> Index Scan using domains_pkey on domains (cost=0.00..8.27 rows=1 width=150)
Index Cond: (domains.id = addresses.domain_id)
Filter: (domains.active AND domains.selfmgmt)
(9 rows)
使用“GROUP BY”:
Group (cost=16.56..16.57 rows=1 width=150)
-> Sort (cost=16.56..16.56 rows=1 width=150)
Sort Key: domains.name, domains.id
-> Nested Loop (cost=0.00..16.55 rows=1 width=150)
-> Index Scan using index_addresses_on_mailbox_id on addresses (cost=0.00..8.27 rows=1 width=4)
Index Cond: (mailbox_id = 1)
-> Index Scan using domains_pkey on domains (cost=0.00..8.27 rows=1 width=150)
Index Cond: (domains.id = addresses.domain_id)
Filter: (domains.active AND domains.selfmgmt)
(9 rows)
我真的不确定如何确定检索这些数据的更好方法。我的直觉告诉我选择“GROUP BY”,但我找不到任何足够具体的文档来解决这个问题。
我应该使用“:group”还是“:select => 'DISTINCT'”?这种选择与其他现代 RDBMS 一样吗? Oracle、DB2 或 MySQL(我无权访问这些,因此无法执行测试)?
【问题讨论】:
标签: sql ruby-on-rails postgresql activerecord