3

我想使用 Ruby 的 Sequel 生成如下 SQL 查询:

SELECT * FROM Objects WHERE (color = "red" AND shape = "triangle") OR 
                            (color = "blue" AND shape = "square") OR
                            (color = "green" AND shape = "circle")

我想从条件列表中以编程方式构建此查询,以便可以执行以下操作:

conditions = [[[:color, "red"], [:shape, "triangle"]],
              [[:color, "blue"], [:shape, "square"]],
              [[:color, "green"], [:shape, "circle"]]]
DB[:Users].where(conditions.sql_or)

它不必遵循那种确切的形式,但我希望能够以编程方式构建条件,因此仅仅能够手动构建这个查询是不够的。

4

2 回答 2

2

尝试这个:

conditions = [ 
               {:color => "red", :shape => "triangle"},
               {:color => "blue", :shape => "square"},
               {:color => "green", :shape => "circle"}
             ]

head, *tail = *conditions

tail.inject(DB[:Users].filter(head)){|mem,obj| mem.or(obj) }

我得到:

=> #<Sequel::Postgres::Dataset: "SELECT * FROM \"Users\" WHERE (((\"color\" = 'red') AND (\"shape\" = 'triangle')) OR ((\"color\" = 'blue') AND (\"shape\" = 'square')) OR ((\"color\" = 'green') AND (\"shape\" = 'circle')))">
于 2012-10-23T19:00:57.887 回答
1

我认为这将使用不同的 SQL 查询返回等效结果:

DB[:Objects].where('(color, shape) in ?', conditions.sql_value_list).sql
=> "SELECT * FROM `Objects` WHERE ((color, shape) in (('red', 'triangle'), ('blue', 'square'), ('green', 'circle')))"

sql_value_list记录在http://sequel.rubyforge.org/rdoc/classes/Array.html

否则使用:

objects = DB[:Objects].where(conditions[0])
conditions[1 .. -1].each { |c| objects = objects.or(c) }

结果是:

SELECT * FROM `Objects` WHERE (((`color` = 'red') AND (`shape` = 'triangle')) OR ((`color` = 'blue') AND (`shape` = 'square')) OR ((`color` = 'green') AND (`shape` = 'circle')))

我在看Iain的回答,和我的第二个基本一样,只是更简洁一些;我喜欢它的优雅。

于 2012-10-23T19:54:10.173 回答