代码之家  ›  专栏  ›  技术社区  ›  Dominic Rodger

联接到联接项具有多行的表

  •  1
  • Dominic Rodger  · 技术社区  · 15 年前

    我有一张桌子 users 它有一个主键 userid 和日期时间列 pay_date .

    我还有一张桌子 user_actions 哪些参考文献 用户 通过柱子 用户标识 和日期时间列 action_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
    

    但很明显,这会为每个用户返回多行(对于发生在或之后的每个用户操作都返回一行) 支付日期 )你知道从这里去哪里吗?

    抱歉,这可能是一个简单的问题,我对T-SQL还比较陌生。

    3 回复  |  直到 15 年前
        1
  •  4
  •   Dominic Rodger    15 年前

    如果你有 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
  •  5
  •   A-K    15 年前

    交叉申请是您的朋友:

    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
    
        3
  •  0
  •   gbn    15 年前
    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)