给出一个表("表")如下(对于CSV样式很抱歉,因为我不知道如何使它看起来像使用Stack Overflow编辑器的表):
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
如果使用Ruby Sequel,我应该如何编写查询,以便获得以下数据集。
id,member,data,start,end 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
我从原始表中获取EACH(不同)成员的最新(最大结束日期值)记录。
如果我将表转换为数组,我可以得到答案,但我正在寻找SQL或Ruby Sequel查询的解决方案,如果可能的话。谢谢。
额外的功劳:这篇文章的标题是蹩脚的...但我不能提出一个好的。如果你有一个,请提供更好的标题。谢谢。
答案 0 :(得分:0)
结果的标准是什么?
如果是键1,3和4,您可以使用DB[:mytable].filter( :id => [1,3,4])
(下面的完整示例)
有关使用续集过滤的详细信息,请参阅sequel documentation,尤其是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
答案 1 :(得分:0)
在我看来,你是从错误的一方接近问题。 ORM(和Sequel一样)代表了数据库上方一个不错的DSL-ish层,但是,在下面,它就是那里的所有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
现在你应该看看如何在续集中执行左连接,你也需要别名表。不应该那么难。
答案 2 :(得分: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
这会给你相同的结果。