Проблема с добавлением пользовательских sql в условия поиска - PullRequest
1 голос
/ 11 марта 2009

Я пытаюсь добавить следующий пользовательский sql к условию поиска, и есть что-то не совсем правильное. Я не являюсь экспертом по sql, но у меня это получилось с другом, который ... rubyonrails или activerecord или искатель)

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 (: все,: включить => [{: клиент => [: агент,: source_id,: source_code]}, {: status_changes =>: состояние}], : Условия => [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):

в чем здесь основная неисправность - почему она жалуется на столбцы?

Ответы [ 2 ]

1 голос
/ 11 марта 2009

Модификатор условий ожидает условие (например, логическое выражение, которое может входить в предложение where), и вы передаете ему весь запрос (оператор выбора).

Похоже, что вы пытаетесь сделать слишком много за один раз, и вам следует разбить его на более мелкие шаги. Несколько предложений:

  • используйте запрос с find_by_sql и не связывайтесь с условиями.
  • использовать поиск рельсов и фильтровать записи в коде рельсов

Также обратите внимание, что построение запроса таким способом небезопасно, если такие значения, как status_date_start, могут поступать от пользователей. Посмотрите «SQL-инъекции», чтобы увидеть, в чем проблема, и прочитайте документацию и примеры по rails для find_by_sql, чтобы узнать, как их избежать.

0 голосов
/ 11 марта 2009

Хорошо, мне удалось переоборудовать его, чтобы он был более дружественным к модификатору условий, и я думаю, что он правильно выполняет запрос 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])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...