2009-07-09 28 views
1

私はテーブルusersにプライマリキーuseridとdatetimeカラムpay_dateを持っています。結合アイテムの複数の行を持つテーブルへの結合

またuser_actionsというテーブルは、useridusersという列と、datetime列のaction_dateを参照しています。

action_dateの後にpay_dateの後にあるuser_actionsテーブルから最も早いアクションのみを取り出して、2つのテーブルを結合したいとします。

私のような事をしようとしている:

select users.userid from users 
left join user_actions on user_actions.userid = users.userid 
where user_actions.action_date >= users.pay_date 
order by user_actions.pay_date 

しかし、明らかにそれは私に、ユーザーごとに複数の行(pay_date日以降に発生したすべてのユーザーアクションの1)を返します。ここからどこへ行くの?

おそらく簡単な質問のように思えるのは、私はかなりt-SQLに慣れています。

答えて

4

あなたはPRIMARY KEYuser_actionsにしている場合:

SELECT u.*, ua.* 
FROM users u 
LEFT JOIN 
     user_actions ua 
ON  user_actions.id = 
     (
     SELECT TOP 1 id 
     FROM user_actions uai 
     WHERE uai.userid = u.userid 
       AND uai.action_date >= u.pay_date 
     ORDER BY 
       uai.action_date 
     ) 

そうでない場合は、次の

WITH j AS 
     (
     SELECT u.*, ua.*, ROW_NUMBER() OVER (PARTITION BY ua.userid ORDER BY ua.action_date) AS rn, ua.action_date 
     FROM users u 
     LEFT JOIN 
       user_actions ua 
     ON  ua.userid = u.userid 
       AND ua.action_date >= u.pay_date 
     ) 
SELECT * 
FROM j 
WHERE rn = 1 or action_date is null 

更新:@AlexKuznetsovによって提案された

CROSS APPLYよりエレガントかつ効率的です。

+0

んuser_ActionsテーブルはIDを持っていると仮定していますか? –

+0

最初の解決策は(投稿のとおり)、2番目の解決策はありません。 – Quassnoi

+0

ありがとうございます - それは私が欲しいものです。そのような行動が存在しないユーザーを維持することは可能ですか?私は 'user_actions'テーブルから一つの値(' ua.action_date')を取り出したいだけです。そのようなアクションが存在しなければnullにしたいと思います。あなたが時間を持っていない場合でも心配はありません、私の質問に完全に答えたので、私はあなたを+1しました。 –

0
select u.*, ua.* from 
    users u join users_actions ua on u.userid = ua.userid 
where 
    ua.action_date in 
      (select min(action_date) from user_actions ua1 
      where 
        ua1.action_date >= u.pay_date and 
        u.userid=ua1.userid) 
5

CROSS APPLYはあなたの友達です:

select users.*, t.* from users 
CROSS APPLY(SELECT TOP 1 * FROM user_actions WHERE user_actions.userid = users.userid 
AND user_actions.action_date >= users.pay_date 
order by user_actions.pay_date) AS t 
+1

ニースポイント、+1。 – Quassnoi

+0

これは、@ Quassnoiの提案よりもかなり遅く、 'user'に' user_actions'がないことを考慮していません。元の質問にも答えます。だから+1! –

関連する問題