Sql 根据其他表中的条件在表中选择记录
在我正在使用的rails应用程序中,我有以下设置:Sql 根据其他表中的条件在表中选择记录,sql,ruby-on-rails-3,postgresql,join,scope,Sql,Ruby On Rails 3,Postgresql,Join,Scope,在我正在使用的rails应用程序中,我有以下设置: class Volunteer < AR::Base has_many :engagements end class Engagement < AR::Base belongs_to :volunteer end 我正在将这些作用域与其他作用域合并以筛选志愿者 上述作用域:not_engaged_between生成以下SQL: SELECT "volunteers".* FROM "volunteers" INNER J
class Volunteer < AR::Base
has_many :engagements
end
class Engagement < AR::Base
belongs_to :volunteer
end
我正在将这些作用域与其他作用域合并以筛选志愿者
上述作用域:not_engaged_between生成以下SQL:
SELECT "volunteers".* FROM "volunteers" INNER JOIN "accounts" ON "accounts"."user_id" = "volunteers"."id" AND "accounts"."user_type" = 'Volunteer' INNER JOIN "engagements" ON "engagements"."volunteer_id" = "volunteers"."id" WHERE (accounts.activation_state = 'active') AND (engagements.date NOT BETWEEN '2012-07-30' AND '2012-08-04')
问题是志愿者可能到目前为止没有任何约会,在这种情况下,查询完全忽略了这些志愿者。即使志愿者没有任何约会,我如何让他们返回 您需要一个不存在的文件来执行此操作。这种语法对SQL来说有点重,也许有更好的arel方法
scope :not_engaged_on, lambda { |q| where(["NOT EXISTS (SELECT ID from engagements WHERE engagements.date = ? AND volunteer_id = volunteers.id)", q])}
scope :not_engaged_between, lambda { |s, e| where(["NOT EXISTS (SELECT ID from engagements WHERE engagements.date BETWEEN ? AND ? AND volunteer_id = volunteers.id)", s, e]) }
您需要一个不存在的文件来执行此操作。这种语法对SQL来说有点重,也许有更好的arel方法
scope :not_engaged_on, lambda { |q| where(["NOT EXISTS (SELECT ID from engagements WHERE engagements.date = ? AND volunteer_id = volunteers.id)", q])}
scope :not_engaged_between, lambda { |s, e| where(["NOT EXISTS (SELECT ID from engagements WHERE engagements.date BETWEEN ? AND ? AND volunteer_id = volunteers.id)", s, e]) }
@Anthony已经提到了不存在。另一个选项是+检查是否存在e.U id为空: 在这种情况下,您必须将条件e.date在“2012-07-30”和“2012-08-04”之间移动到join子句中
如果帐户也可能丢失,请使用另一个左联接。但您似乎确实想检查用户类型和激活状态。@Anthony已经提到的不存在。另一个选项是+检查是否存在e.U id为空: 在这种情况下,您必须将条件e.date在“2012-07-30”和“2012-08-04”之间移动到join子句中
如果帐户也可能丢失,请使用另一个左联接。但您似乎确实想检查用户类型和激活状态。谢谢您的回答。但是,抛出NoMethodError:for的未定义方法'default\u scoped'。有什么想法吗?好的,我的答案。这可能不是最好的语法,但应该可以。谢谢你的帮助。不知何故,exists.not syntax和not exists对我不起作用。必须这样做才能使它工作:作用域:not|engaged|between,lambda{s,e|joinsLEFT JOIN engagements e ON e.志愿者id=志愿者.id和e.date不在{s}和{e}之间。其中[e.志愿者| id为NULL]},这将生成@Erwin建议的SQL。再次感谢你的帮助!由于我正在构建作用域并在运行查询之前合并它们,所以这种方法现在对我更有效,谢谢。谢谢你的回答。但是,抛出NoMethodError:for的未定义方法'default\u scoped'。有什么想法吗?好的,我的答案。这可能不是最好的语法,但应该可以。谢谢你的帮助。不知何故,exists.not syntax和not exists对我不起作用。必须这样做才能使它工作:作用域:not|engaged|between,lambda{s,e|joinsLEFT JOIN engagements e ON e.志愿者id=志愿者.id和e.date不在{s}和{e}之间。其中[e.志愿者| id为NULL]},这将生成@Erwin建议的SQL。再次感谢你的帮助!因为我正在构建范围并在运行查询之前将其合并,所以这种方法现在对我更有效,谢谢。谢谢。它是有效的,我必须这样定义它以生成所需的SQL:scope:not|engaged|between,lambda{s,e|joinsLEFT JOIN-engagements e ON e.志愿者id=志愿者.id和e.date不在{s}和{e}之间,其中[e.志愿者| id为NULL]}。再次感谢!!谢谢它是有效的,我必须这样定义它以生成所需的SQL:scope:not|engaged|between,lambda{s,e|joinsLEFT JOIN-engagements e ON e.志愿者id=志愿者.id和e.date不在{s}和{e}之间,其中[e.志愿者| id为NULL]}。再次感谢!!
SELECT v.*
FROM volunteers v
JOIN accounts a ON a.user_id = v.id
LEFT JOIN engagements e ON e.volunteer_id = v.id
AND e.date BETWEEN '2012-07-30' AND '2012-08-04'
WHERE a.user_type = 'Volunteer'
AND a.activation_state = 'active'
AND e.volunteer_id IS NULL;