1

外部キーを介してテーブルと1対多の関係にあるテーブルがありusersます。つまり、各ユーザーは多くの購入を行うことができます(または、何も購入しない場合は、user_purchasesテーブルにエントリがありません)。user_purchasesuser_id

user_purchasesここで関心のある他のフィールドは1つだけです。それはpurchase_dateです。

次の列を持つデータセットを返すSequelORMステートメントを作成しようとしています。

  • ユーザーID
  • ユーザーの2番目の購入日(存在する場合)

したがって、2回以上購入していないユーザーは、このデータセットに表示されません。この続編のステートメントを書くための最良の方法は何ですか?

2回以上購入したすべてのユーザーが戻ってきたデータセットを探していることに注意してください

ありがとう!

明確にするために編集

これは、ユーザーとその最初の購入日を取得するために私が書いた同様のステートメントです(現在の投稿で助けを求めている2番目の購入日とは対照的です):

   DB[:users].join(:user_purchases, :user_id => :id)
              .select{[:user_id, min(:purchase_date)]}
              .group(:user_id)
4

3 に答える 3

2

あなたは日付について心配していないようです、ただ数えます

DB[:user_purchases].group_and_count(:user_id).having(:count > 1).all

(購入の)カウントが2以上のuser_idsとカウントのリストを返します。

[{:count=>2, :user_id=>1}, {:count=>7, :user_id=>2}, {:count=>2, :user_id=>3}, ...]

それを使用してユーザーを取得したい場合、Sequelを使用する最も簡単な方法は、user_idのリストだけを抽出し、それを別のクエリにフィードバックすることです。

DB[:users].where(:id => DB[:user_purchases].group_and_count(:user_id).
    having(:count > 1).all.map{|row| row[:user_id]}).all

編集:

もっと簡潔な方法があるはずだと感じたので、https: //stackoverflow.com/a/10886982/131226を使用select_groupして別の質問に対するこの回答(続編の著者Jeremy Evansから)を見ましたselect_more

これは、副選択なしでそれを行う必要があります:

DB[:users].
  left_join(:user_purchases, :user_id=>:id).
  select_group(:id).
  select_more{count(:purchase_date).as(:purchase_count)}.
  having(:purchase_count > 1)

このSQLを生成します

SELECT `id`, count(`purchase_date`) AS 'purchase_count' 
FROM `users` LEFT JOIN `user_purchases` 
ON (`user_purchases`.`user_id` = `users`.`id`) 
GROUP BY `id` HAVING (`purchase_count` > 1)"
于 2012-11-13T05:26:18.323 に答える
0

通常、これは必要なSQLクエリである可能性があります。

SELECT u.id, up1.purchase_date FROM users u
LEFT JOIN user_purchases up1 ON u.id = up1.user_id
LEFT JOIN user_purchases up2 ON u.id = up2.user_id AND up2.purchase_date < up1.purchase_date
GROUP BY u.id, up1.purchase_date
HAVING COUNT(up2.purchase_date) = 1;

より良い答えが得られない場合は、それを続編に変換してみてください。

于 2012-11-02T17:16:19.577 に答える
0

ユーザーの2回目の購入日は、クエリの一部としてを実行した場合に取得される2番目の行になりorder_by(:purchase_date)ます。

これにアクセスするにはlimit(2)、クエリを2つの結果に制限してから、[-1](またはlast)1つを取得します。したがって、モデルを使用せず、データセットのみを使用していて、user_id関心があることがわかっている場合、(テストされていない)クエリは次のようになります。

DB[:user_purchases].where(:user_id => user_id).order_by(:user_purchases__purchase_date).limit(2)[-1]

Sequelのコンソールからの出力は次のとおりです。

DB[:user_purchases].where(:user_id => 1).order_by(:purchase_date).limit(2).sql
=> "SELECT * FROM user_purchases WHERE (user_id = 1) ORDER BY purchase_date LIMIT 2"

select適切な句を追加します。

.select(:user_id, :purchase_date)

そして、あなたは行われるべきです:

DB[:user_purchases].select(:user_id, :purchase_date).where(:user_id => 1).order_by(:purchase_date).limit(2).sql
=> "SELECT user_id, purchase_date FROM user_purchases WHERE (user_id = 1) ORDER BY purchase_date LIMIT 2"
于 2012-11-02T17:20:43.653 に答える