所以,我有一个问题。我有一个查询从一个表(比如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类型 此外,当我执行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数组? 我发现了答案,但找不到合适的答案。
编辑:我只能对query1使用Active Record,如果是这种情况,并且ids是Active Record对象,任何人都可以建议如何在IN子句中将它传递给query2是一个原始的SQL查询?
Edit2 :我无法使用Active Record(用于query2)或加入,因为它会使查询繁重并需要很长时间(> 10s)来获取结果(索引存在)。所以,我正在使用原始查询来优化它。
答案 0 :(得分:2)
你确定它不起作用,因为它是一个字符串。我认为它不起作用,因为重复括号。请试试这个:
array = ids.flat_map(&:values).join(',')
query2 = %Q{select * from table2 where `table2`.`table1_id` IN (#{array}) and status="rejected"}
我建议使用ORM (object-relational mapping)或ActiveRecord
宝石之类的Sequel
- 特别是因为通过字符串连接手动构建数据库查询容易出错并导致sql注入等漏洞。
答案 1 :(得分:2)
当我运行类似的查询以尝试模仿您的问题时,我看到我正在获取ids
的数组数组,例如[["1"], ["2"], ["3"]]
。
如果这也是你得到的,那么你应该在致电ids.flatten
之前致电join
:
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
转换为如下所示的哈希数组:
[{"id"=>"1"}, {"id"=>"2"}]
然后使用map(&:values)
我们将其转换为如下所示的数组:
[["1"], ["2"]]
此数组与上述(编辑前)类似,因此运行flatten.join(',')
会将其转换为您要查找的字符串。
请注意,您可以使用共同的快捷方式map(&:values).flatten
而不是flat_map(&:values)
,这会产生相同的结果。
答案 2 :(得分:0)
如果您发布的主要原因是学习如何从散列数组中提取数据,那么您可以忽略此答案。
但是,如果您想要从数据库获取数据的最佳方式,我建议您使用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
会为您执行此操作,并允许您添加其他查询,以便您可以在一个查询中收集所需的数据。
答案 3 :(得分:-1)
您可以使用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)
它会正常工作。