繁体   English   中英

在Ruby on Rails中传递原始MySQL查询中的数组

[英]Pass array in raw MySQL query in Ruby on Rails

所以,我有一个问题。 我有一个查询从一个表(比如table1)返回id,我必须将这些id传递给另一个使用table2的查询。 (由于某些原因,编写内部选择或连接不是一种选择)。

查询:

client = Mysql2::Client.new(:host => "localhost", :username => "", :password => "", :database =>"test")
query1 = %Q{select id from table1 where code='ABC123'}
ids = client.query(query1)
query2 = %Q{select * from table2 where `table2`.`table1_id` IN (#{ids}) and status="rejected"}
table2_data = client.query(query2)

ids是Mysql2 :: Result type另外,当我执行ids.to_a时,结果数组的数据如下:[{“id”=> 1},{“id”=> 2}]我需要一些可行的方法将id传递给第二个查询。 我尝试了ids.to_a,但由于括号[]而导致错误。 我也试过连接,说MySQL的结果是:

array = ids.to_a  # [1,2,3]
id_new = "("+#{array.join(',')}+")"

id_new变为“(1,2,3)”,这是一个字符串,因此IN不起作用。

任何人都可以建议如何在原始MySQL查询中传递ids数组? 我发现了答案,但找不到合适的答案。

编辑 :我只能为查询1使用Active Record,如果是这种情况,并且ids是一个Active Record对象,有人可以建议如何将它传递给IN子句中的query2,它应该是一个原始的SQL查询吗?

Edit2 :我不能使用Active Record(用于query2)或加入,因为它使查询繁重并花费很长时间(> 10s)来获取结果(索引存在)。 所以,我正在使用原始查询来优化它。

你确定它不起作用,因为它是一个字符串。 我认为它不起作用,因为重复括号。 请试试这个:

array = ids.flat_map(&:values).join(',')
query2 = %Q{select * from table2 where `table2`.`table1_id` IN (#{array}) and status="rejected"}

我建议使用像ActiveRecordSequel宝石一样的ORM(对象关系映射) - 特别是因为通过字符串连接手动构建数据库查询容易出错并导致sql注入等漏洞。

当我跑了类似的查询,试图模仿你的问题,我看到我得到数组的数组, ids ,如[["1"], ["2"], ["3"]]

如果这也是你得到的,那么你应该在调用join之前调用ids.flatten

query2 = %Q{select * from table2 where `table2`.`table1_id` IN (#{ids.flatten.join(',')}) and status="rejected"}

array.flatten删除额外的大括号,所以:

[[1], [2], [3]].flatten
# => [1,2,3]

[[1], [2], [3]].flatten.join(',')
# => "1,2,3"

编辑

由于您报告您正在接收Mysql2::Result对象,请执行以下操作: ids.to_a.map(&:values).flatten.join(',')

to_a首先将Mysql2::Result转换为Mysql2::Result的哈希数组:

[{"id"=>"1"}, {"id"=>"2"}]

然后使用map(&:values)我们将其转换为如下所示的数组:

[["1"], ["2"]]

此数组类似于上面(在编辑之前),因此运行flatten.join(',')会将其转换为您要查找的字符串。

请注意,您可以使用公共快捷方式flat_map(&:values)代替map(&:values).flatten ,这会产生相同的结果。

如果您发布的主要原因是学习如何从散列数组中提取数据,那么您可以忽略此答案。

但是,如果您想从数据库中获取数据的最佳方法,我建议您使用ActiveRecord为您执行驴工作:

class Table1 < ActiveRecord::Base
  self.table_name = :table1
  has_many :table2s
end

class Table2 < ActiveRecord::Base
  self.table_name = :table2
  belongs_to :table1
end

table2_data = Table2.joins(:table1).where(table1: {code: 'ABC123'}, status: 'rejected') 

关键是SQL join将有效地为您处理ID。 您可以自己编写SQL连接的代码,但ActiveRecord会为您执行此操作,并允许您添加其他查询,以便您可以在一个查询中收集所需的数据。

您可以使用comma连接数组,如下面的代码。

ids = ids.to_a.map{|h| h['id']}
query2 = %Q{select * from table2 where `table2`.`table1_id` IN (#{ids.join(',')}) and status="rejected"}  
table2_data = client.query(query2)

它会工作正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM