1

次のようなテーブル (「テーブル」) があるとします (スタック オーバーフロー エディターでテーブルのように見せる方法がわからないため、CSV スタイルについては申し訳ありません)。

ID、メンバー、データ、開始、終了
1,001,abc,12/1/2012,12/31/2999
2,001,def,2009/1/1,2012/11/30
3,002,ghi,1/1/2009,12/31/2999
4,003、jkl、2012 年 1 月 1 日、2012 年 10 月 31 日
5,003、月、2011 年 8 月 1 日、2011 年 12 月 31 日

Ruby Sequel を使用している場合、クエリをどのように記述すれば、次のデータセットが返されるのでしょうか。

ID、メンバー、データ、開始、終了
1,001,abc,12/1/2012,12/31/2999
3,002,ghi,1/1/2009,12/31/2999
4,003、jkl、2012 年 1 月 1 日、2012 年 10 月 31 日

元のテーブルから、各 (個別の) メンバーの最新 (最大の終了日の値) のレコードを取得します。

テーブルを配列に変換すれば答えが得られるのですが、可能であればSQLやRubyのSequelクエリで解決策を探しています。ありがとうございました。

追加のクレジット: この投稿のタイトルは下手ですが、いいタイトルが思いつきません。いいタイトルがあれば教えてください。ありがとうございました。

4

3 に答える 3

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

これの続編はちょっと怖い。私が理解できる最善の方法は、副選択を使用することです。2 つの列でテーブルと副選択を結合する必要があるため、「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"}

この場合、最後の 4 行を単純な 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 に答える
0

あなたの結果の基準は何ですか?

それがキー1、3、および4の場合は、使用できますDB[:mytable].filter( :id => [1,3,4])(以下の完全な例)

続編を使用したフィルタリングの詳細については、続編のドキュメント、特にデータセット フィルタリングを参照してください。

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 に答える