我正在尝试将以下自定义sql添加到finder条件中并且有一些不太正确的事情..我不是一个sql专家但是这个问题与一个朋友一起解决了..(但他们并不熟悉rubyonrails或activerecord或finder)
status_search = "select p.*
from policies p
where exists
(select 0 from status_changes sc
where sc.policy_id = p.id
and sc.status_id = '"+search[:status_id].to_s+"'
and sc.created_at between "+status_date_start.to_s+" and "+status_date_end.to_s+")
or exists
(select 0 from status_changes sc
where sc.created_at =
(select max(sc2.created_at)
from status_changes sc2
where sc2.policy_id = p.id
and sc2.created_at < "+status_date_start.to_s+")
and sc.status_id = '"+search[:status_id].to_s+"'
and sc.policy_id = p.id)" unless search[:status_id].blank?
我的发现声明: Policy.find(:所有,:包括=&GT; [{:客户=&GT; [:剂:SOURCE_ID,:source_code]},{:status_changes =&GT;:状态}], :条件=&GT; [status_search])
我在日志中收到此错误消息:
ActiveRecord::StatementInvalid (Mysql::Error: Operand should contain 1 column(s): SELECT DISTINCT `policies`.id FROM `policies` LEFT OUTER JOIN `clients` ON `clients`.id = `policies`.client_id WHERE ((((policies.created_at BETWEEN '2009-01-01' AND '2009-03-10' OR policies.created_at = '2009-01-01' OR policies.created_at = '2009-03-10')))) AND (select p.*
from policies p
where exists
(select 0 from status_changes sc
where sc.policy_id = p.id
and sc.status_id = '2'
and sc.created_at between 2009-03-10 and 2009-03-10)
or exists
(select 0 from status_changes sc
where sc.created_at =
(select max(sc2.created_at)
from status_changes sc2
where sc2.policy_id = p.id
and sc2.created_at < 2009-03-10)
and sc.status_id = '2'
and sc.policy_id = p.id)) ORDER BY clients.created_at DESC LIMIT 0, 25):
这里的主要故障是什么 - 它为什么抱怨这些列?
答案 0 :(得分:1)
condition修饰符期望一个条件(例如一个可以放在where子句中的布尔表达式),并且你传递一个完整的查询(一个select语句)。
看起来好像你想在这里一次做太多,并且应该把它分解成更小的步骤。一些建议:
find_by_sql
一起使用,不要弄乱条件。另外,请注意,如果像status_date_start
这样的值可以来自用户,则以这种方式构建查询并不安全。查看“sql注入攻击”以查看问题所在,并阅读rails文档&amp; find_by_sql
的示例,了解如何避免它们。
答案 1 :(得分:0)
好吧,我已经设法重新调整了这个,所以它对条件修饰符更友好,我认为它正在正确地执行sql查询..但是,当我尝试列出当前状态时,它返回的策略( policy.status_change.last.status)它被设置为查询中使用的相同状态 - 这是不正确的
这是我更新的条件字符串..
status_search = "status_changes.created_at between ? and ? and status_changes.status_id = ?) or
(status_changes.created_at = (SELECT MAX(sc2.created_at) FROM status_changes sc2
WHERE sc2.policy_id = policies.id and sc2.created_at < ?) and status_changes.status_id = ?"
有什么显而易见的东西,一旦在查询中找到一个,就不会返回所有剩余的相关状态变化吗?
这是更新后的发现..
Policy.find(:all,:include=>[{:client=>[:agent,:source_id,:source_code]},:status_changes],
:conditions=>[status_search,status_date_start,status_date_end,search[:status_id].to_s,status_date_start,search[:status_id].to_s])