2016-05-31 127 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