1

给定一个表格(“表格”)如下(对于 CSV 样式感到抱歉,因为我不知道如何使用 Stack Overflow 编辑器使它看起来像一个表格):

ID,成员,数据,开始,结束
1,001,abc,12/1/2012,12/31/2999
2,001,def,1/1/2009,11/30/2012
3,002,ghi,1/1/2009,12/31/2999
4,003,jkl,1/1/2012,10/31/2012
5,003,mno,8/1/2011,12/31/2011

如果使用 Ruby Sequel,我应该如何编写查询,以便获得以下数据集作为回报。

ID,成员,数据,开始,结束
1,001,abc,12/1/2012,12/31/2999
3,002,ghi,1/1/2009,12/31/2999
4,003,jkl,1/1/2012,10/31/2012

我从原始表中获取每个(不同)成员的最新(最大结束日期值)记录。

如果我将表转换为数组,我可以得到答案,但如果可能的话,我正在寻找 SQL 或 Ruby Sequel 查询中的解决方案。谢谢你。

额外的功劳:这篇文章的标题很蹩脚……但我想不出一个好的标题。如果你有,请提供一个更好的标题。谢谢你。

4

3 回答 3

0

你的结果的标准是什么?

如果是键 1,3 和 4,您可以使用DB[:mytable].filter( :id => [1,3,4])(下面的完整示例)

有关使用 sequel 进行过滤的更多信息,请参阅sequel 文档,尤其是Dataset Filtering

require 'csv'
require 'sequel'

#Create Test data     
DB = Sequel.sqlite()
DB.create_table(:mytable){
  field :id
  field :member
  field :data
  field :start #should be date, not implemented in example
  field :end   #should be date, not implemented in example
}
CSV.parse(<<xx
id,member,data,start,end
 1,001,abc,12/1/2012,12/31/2999
 2,001,def,1/1/2009,11/30/2012
 3,002,ghi,1/1/2009,12/31/2999
 4,003,jkl,1/1/2012,10/31/2012
 5,003,mno,8/1/2011,12/31/2011
xx
 ).each{|x|
  DB[:mytable].insert(*x)
}
#Create Test data - end -

puts DB[:mytable].filter( :id => [1,3,4]).all
于 2013-01-04T22:01:17.197 回答
0

在我看来,你是从错误的角度来解决问题的。ORM(以及 Sequel)在数据库之上代表了一个不错的 DSL 层,但在其之下,全是 SQL。因此,我会尝试以某种方式制定问题和答案,以获取 SQL 查询,该查询将返回您需要的内容,然后看看它如何翻译成 Sequel 的语言。

您需要按成员分组并获取每个成员的最新记录,对吗?

我会采用以下想法(大致):

SELECT t1.*
FROM table t1
LEFT JOIN table t2 ON t1.member = t2.member AND t2.end > t1.end
WHERE t2.id IS NULL

现在您应该了解如何在 Sequel 中执行左连接,并且您还需要给表起别名。不应该那么难。

于 2013-01-05T08:06:49.033 回答
0

这个的续集版本有点吓人。我能想到的最好的方法是使用子选择,因为您需要在两列上连接表和子选择,所以使用“连接块”,如Querying in Sequel中所述。这是上面 Knut 程序的修改版本:

require 'csv'
require 'sequel'

# Create Test data     
DB = Sequel.sqlite()
DB.create_table(:mytable){
  field :id
  String :member
  String :data
  String :start # Treat as string to keep it simple
  String :end   # Ditto
}
CSV.parse(<<xx
  1,"001","abc","2012-12-01","2999-12-31"
  2,"001","def","2009-01-01","2012-11-30"
  3,"002","ghi","2009-01-01","2999-12-31"
  4,"003","jkl","2012-01-01","2012-10-31"
  5,"003","mno","2011-08-01","2011-12-31"
xx
).each{|x|
  DB[:mytable].insert(*x)
}

# That was all setup, here's the query
ds = DB[:mytable]
result = ds.join(ds.select_group(:member).select_append{max(:end).as(:end)}, :member=>:member) do |j, lj, js|
  Sequel.expr(Sequel.qualify(j, :end) => Sequel.qualify(lj, :end))
end
puts result.all

这给了你:

{:id=>1, :member=>"001", :data=>"abc", :start=>"2012-12-01", :end=>"2999-12-31"}
{:id=>3, :member=>"002", :data=>"ghi", :start=>"2009-01-01", :end=>"2999-12-31"}
{:id=>4, :member=>"003", :data=>"jkl", :start=>"2012-01-01", :end=>"2012-10-31"}

在这种情况下,用直接的 SQL 替换最后四行可能更容易。就像是:

puts DB[
  "SELECT a.* from mytable as a 
  join (SELECT member, max(end) AS end FROM mytable GROUP BY member) as b 
  on a.member = b.member and a.end=b.end"].all

这会给你同样的结果。

于 2013-01-16T01:40:26.097 回答