我有一个表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相当新。
答案 0 :(得分: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 :(得分:4)
如果PRIMARY KEY
上有user_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
更优雅高效。
答案 2 :(得分: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)