如何使用续集结合AND和OR?

时间:2012-10-23 18:41:18

标签: sql ruby database sequel

我想使用Ruby的续集生成如下的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)

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

2 个答案:

答案 0 :(得分: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')))">

答案 1 :(得分: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的答案,它和我的第二个答案基本相同,只是更简洁;我喜欢它的优雅。