2012-10-23 98 views
2

我想产生类似下面的使用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) 

它不一定要遵循确切的形式,但我希望能够以编程方式构建条件,所以仅靠手工构建此查询是不够的。

+0

*使用SQL *生成SQL查询...您刚刚向我们展示了SQL查询。你能澄清你的要求吗? – Kermit

+0

@njk用“Ruby's Sequel”替换第二个“SQL”。我已经应用了一个编辑。 – iain

回答

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')))"> 
+0

+1。它让我的头部受伤了一分钟,因为我从来没有考虑过在Sequel数据集中使用“注入”,但然后点击它。做得很好。 –

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'))) 

我看着伊恩的回答,这是基本相同,我的第二个,只有更简洁;我喜欢它的优雅。

相关问题