2016-05-31 90 views
3

我有一个类似于LIMITing a SQL JOIN的问题,但有一个稍微复杂的要求。限制SQL JOIN,加入条件

我要搜索用户和关联交易,其位于一时间范围内:

SELECT u.*, t.* 
FROM User u 
JOIN Transaction t ON t.user_id = u.id 
WHERE t.timestamp >= ? and t.timestamp <= ?; 

到目前为止,一切都很好。现在我想重复查询,但是返回的用户数量有LIMIT。尽管如此,给定用户返回的交易数量应该没有限制。

如果我按照在其他问题提出的办法,将其转化为:

SELECT u.*, t.* 
FROM (SELECT * FROM User LIMIT 10) u 
JOIN Transaction t ON t.user_id = u.id 
WHERE t.timestamp >= ? and t.timestamp <= ?; 

这不会产生我想要的东西:它会返回第10个用户,谁可能没有任何相关交易。

我想返回10个用户谁在给定的时间范围内至少有一个关联交易

我怎样才能实现这个使用MySQL?

回答

1

可以使用变量此:

SELECT * 
FROM (
    SELECT *, 
     @rn := IF(@uid = user_id, @rn, 
        IF(@uid := user_id, @rn +1, @rn + 1)) AS rn 
    FROM (
    SELECT u.*, t.* 
    FROM User u 
    JOIN Transaction t ON t.user_id = u.id 
    WHERE t.timestamp >= x and t.timestamp <= y) AS t 
    CROSS JOIN (SELECT @rn := 0, @uid := 0) AS vars 
    ORDER BY user_id) AS x 
WHERE x.rn <= 10 

变量@rn由1每一个新用户的查询返回的时间增加。所以我们可以控制使用@rn <= 10返回的用户数量。

+0

谢谢,这确实有效,除了在第二个IF()的末尾丢失关闭括号。这两个子选择会对性能产生影响吗? – Benjamin

+0

另外,想一想更多一点,它在我看来,MySQL将不得不读取原始JOIN的完整结果(所有行)(可能在临时表中?),然后才执行第一个外部SELECT。如果你有很多用户,那么这难道不是一个巨大的性能瓶颈吗?只有少数用户拥有匹配的交易? – Benjamin

+0

@Benjamin您可以使用您的实际数据测试所有建议的查询,并告诉我们他们如何比较对方。 –

1

你可以做到这一点不变量,但它需要重复join逻辑:

SELECT u.*, t.* 
FROM (SELECT * 
     FROM User 
     WHERE EXISTS (SELECT 1 
        FROM Transaction t 
        WHERE t.user_id = u.id AND 
          t.timestamp >= ? and t.timestamp <= ? 
        ) 
     LIMIT 10 
    ) u JOIN 
    Transaction t 
    ON t.user_id = u.id 
WHERE t.timestamp >= ? and t.timestamp <= ?; 

编辑:

可能是最快的答案是这样的:

select u.*, t.* 
from (select user_id 
     from (select user_id 
      from transaction t 
      where t.timestamp >= ? and t.timestamp <= ? 
      limit 1000 
      ) t 
     limit 30 
    ) tt join 
    user u 
    on tt.userid = u.id join 
    transaction t 
    on tt.userid = t.userid and t.timestamp >= ? and t.timestamp <= ?; 

第一子查询在事务表中选择1,000个匹配记录。我的猜测是,这足以获得30个用户。然后将此列表连接到用户和交易表以获得最终结果。通过限制列表而不必执行全表扫描,第一个查询应该非常快。 。 。尤其是在(timestamp, user)附加索引。

+0

谢谢,我自己并不喜欢基于变量的查询,但重复JOIN更麻烦,我会说,尤其是如果查询变得更复杂(而且会)。无论如何,重复JOIN的性能影响是什么? MySQL是否必须两次完成这项工作,还是在某处执行了性能优化? – Benjamin