2009-07-09 65 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