2009-07-09 71 views
1

我有一个表users,它有一个主键userid和日期时间列pay_date加入到具有多个行的表中的连接项

我也有一个表user_actions,其中users通过列userid和日期时间列action_date

我想将两个表连接在一起,只提取user_actions表中的最早动作,其中action_date的长度小于或等于pay_date

我想要的东西:

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后每用户操作)。任何想法从哪里去?

对于可能看起来像一个简单问题的道歉,我对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 

更新:

CROSS APPLY通过@AlexKuznetsov提出更优雅和高效。

+0

这是否承担user_Actions表有一个ID? – 2009-07-09 15:03:43

+0

第一个解决方案(正如帖子所说),第二个解决方案不。 – Quassnoi 2009-07-09 15:09:06

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