2016-04-23 67 views
1

我的應用程序對locationId,scoreDateTime,分數和評論列使用分數表。用戶可以評分一個位置並且可以選擇提交評論一個小的數據集可能看起來如下:將SQL查詢與2個子查詢合併在一起where條款

mysql> select locationId, scoreDateTime, score, comments from scores; 
+-----------------------------+-------------------------+-------+--------------------------------+ 
| locationId     | scoreDateTime   | score | comments      | 
+-----------------------------+-------------------------+-------+--------------------------------+ 
| ChIJqZyf8O8F44kRbNWHQkDkpGQ | 2016-04-17 17:30:32.899 |  3 | asdfasf      | 
| ChIJqZyf8O8F44kRbNWHQkDkpGQ | 2016-04-17 18:28:46.221 |  3 |        | 
| ChIJqZyf8O8F44kRbNWHQkDkpGQ | 2016-04-17 18:29:56.395 |  3 | safasf       | 
| ChIJqZyf8O8F44kRbNWHQkDkpGQ | 2016-04-17 18:32:10.358 |  3 |        | 
| ChIJqZyf8O8F44kRbNWHQkDkpGQ | 2016-04-17 18:49:32.262 |  3 |        | 
| ChIJqZyf8O8F44kRbNWHQkDkpGQ | 2016-04-17 18:50:33.693 |  3 |        | 
| ChIJqZyf8O8F44kRbNWHQkDkpGQ | 2016-04-17 19:13:58.456 |  3 |        | 
| ChIJqZyf8O8F44kRbNWHQkDkpGQ | 2016-04-17 19:28:10.435 |  3 | asdfasf      | 
| ChIJqZyf8O8F44kRhatfHL4GYe0 | 2016-04-17 23:20:28.857 |  3 | aasdfasfsfsd     | 
| ChIJqZyf8O8F44kRhatfHL4GYe0 | 2016-04-17 23:22:55.254 |  3 | asdfasfasfsafasfsfasf asdfasfd | 
| ChIJqZyf8O8F44kRhatfHL4GYe0 | 2016-04-17 23:40:37.106 |  3 |        | 
| ChIJpbSR1a4I44kRemEzTpniis8 | 2016-04-19 11:17:41.836 |  5 | adfgadf      | 
| ChIJF1LAoqgI44kR5EWvRqJPUN4 | 2016-04-19 11:17:52.536 |  4 |        | 
+-----------------------------+-------------------------+-------+--------------------------------+ 

我想建立一個單一的查詢,將讓每個位置的下面:

  • 從最近的X小時
  • 得分計數
  • 從最後一個Y天
  • 最新scoreDateTime(或NULL)在最後一個Y天的任何評論的評論數

我的動機是顯示位置,最近的分數,他們的歷史評論數量和最新的評論日期時間(或空值)。這會給我最近的評分計數和評論線索的熱度。

以下查詢有效。但是,重複的locationId列表實際上在生產中要高得多。 問題:我想知道是否有合併2個locationId列表的高性能方法,a.k.a'locationId in(...)'。

select 
    x.locationId, count1, count2, count3, count4, count5, IFNULL(commentCount,0) as commentCount, lastCommentDateTime 
from 

    (select 
     locationId, 
     sum(if (score = 1, 1, 0)) count1, 
     sum(if (score = 2, 1, 0)) count2, 
     sum(if (score = 3, 1, 0)) count3, 
     sum(if (score = 4, 1, 0)) count4, 
     sum(if (score = 5, 1, 0)) count5 
    from 
     scores 
    where 
     scoreDateTime > '2016-04-16 21:38:51.843' and 
     locationId in (
      'ChIJqZyf8O8F44kRbNWHQkDkpGQ', 
      'ChIJqZyf8O8F44kRhatfHL4GYe0', 
      'ChIJCes00a4I44kRKG8zB4KvYTM', 
      'ChIJP-eRLq8I44kRKU6VOpTXqTM', 
      'ChIJpbSR1a4I44kRemEzTpniis8', 
      'ChIJF1LAoqgI44kRip2l7rjO2g4', 
      'ChIJF1LAoqgI44kR5EWvRqJPUN4', 
      'ChIJF1LAoqgI44kRRD_ZvPUmrGA', 
      'ChIJjweq4h0G44kRWoCPQKPdrPM', 
      'ChIJf2tVDB4G44kRTYjhl3sjm8M', 
      'ChIJ_Vg4giEG44kRq2nvtjEn8yA', 
      'ChIJP00qFSMG44kRyKcy2f_S12o' 
     ) 
    group by locationId 
    ) as x 

left join 

    (select 
     locationId, 
     count(comments) as commentCount, 
     max(scoreDateTime) as lastCommentDateTime 
    from 
     scores 
    where 
     comments != "" and 
     scoreDateTime > '2016-01-16 00:00:00.000' and 
     locationId in (
      'ChIJqZyf8O8F44kRbNWHQkDkpGQ', 
      'ChIJqZyf8O8F44kRhatfHL4GYe0', 
      'ChIJCes00a4I44kRKG8zB4KvYTM', 
      'ChIJP-eRLq8I44kRKU6VOpTXqTM', 
      'ChIJpbSR1a4I44kRemEzTpniis8', 
      'ChIJF1LAoqgI44kRip2l7rjO2g4', 
      'ChIJF1LAoqgI44kR5EWvRqJPUN4', 
      'ChIJF1LAoqgI44kRRD_ZvPUmrGA', 
      'ChIJjweq4h0G44kRWoCPQKPdrPM', 
      'ChIJf2tVDB4G44kRTYjhl3sjm8M', 
      'ChIJ_Vg4giEG44kRq2nvtjEn8yA', 
      'ChIJP00qFSMG44kRyKcy2f_S12o' 
     ) 
    group by locationId 
    ) as y 

on x.locationId = y.locationId; 

結果如下所示:

mysql> source ../../query3.sql 
+-----------------------------+--------+--------+--------+--------+--------+--------------+-------------------------+ 
| locationId     | count1 | count2 | count3 | count4 | count5 | commentCount | lastCommentDateTime  | 
+-----------------------------+--------+--------+--------+--------+--------+--------------+-------------------------+ 
| ChIJF1LAoqgI44kR5EWvRqJPUN4 |  0 |  0 |  0 |  1 |  0 |   0 | NULL     | 
| ChIJpbSR1a4I44kRemEzTpniis8 |  0 |  0 |  0 |  0 |  1 |   1 | 2016-04-19 11:17:41.836 | 
| ChIJqZyf8O8F44kRbNWHQkDkpGQ |  0 |  0 |  8 |  0 |  0 |   3 | 2016-04-17 19:28:10.435 | 
| ChIJqZyf8O8F44kRhatfHL4GYe0 |  0 |  0 |  3 |  0 |  0 |   2 | 2016-04-17 23:22:55.254 | 
+-----------------------------+--------+--------+--------+--------+--------+--------------+-------------------------+ 

回答

1

它看起來像你的2個查詢之間的區別是scoreDateTimecomments標準。結合查詢的一種方法是使用條件聚合將這些條件移動到select

另外,mysql會將布爾值計算爲1或0,因此您可以通過刪除if語句來簡化sum調用。

select 
    locationId, 
    sum(score = 1 and scoreDateTime > '2016-04-16 21:38:51.843') count1, 
    sum(score = 2 and scoreDateTime > '2016-04-16 21:38:51.843') count2, 
    sum(score = 3 and scoreDateTime > '2016-04-16 21:38:51.843') count3, 
    sum(score = 4 and scoreDateTime > '2016-04-16 21:38:51.843') count4, 
    sum(score = 5 and scoreDateTime > '2016-04-16 21:38:51.843') count5, 
    sum(comments != "") commentCount, 
    max(case when comments != "" then scoreDateTime end) as lastCommentDateTime 
    from 
    scores 
    where 
    scoreDateTime > '2016-01-16 00:00:00.000' and 
    locationId in (
     'ChIJqZyf8O8F44kRbNWHQkDkpGQ', 
     'ChIJqZyf8O8F44kRhatfHL4GYe0', 
     'ChIJCes00a4I44kRKG8zB4KvYTM', 
     'ChIJP-eRLq8I44kRKU6VOpTXqTM', 
     'ChIJpbSR1a4I44kRemEzTpniis8', 
     'ChIJF1LAoqgI44kRip2l7rjO2g4', 
     'ChIJF1LAoqgI44kR5EWvRqJPUN4', 
     'ChIJF1LAoqgI44kRRD_ZvPUmrGA', 
     'ChIJjweq4h0G44kRWoCPQKPdrPM', 
     'ChIJf2tVDB4G44kRTYjhl3sjm8M', 
     'ChIJ_Vg4giEG44kRq2nvtjEn8yA', 
     'ChIJP00qFSMG44kRyKcy2f_S12o' 
    ) 
    group by locationId 

這種查詢可以在(locationId, scoreDateTime)

+1

採取綜合指數的優勢偉大工程,模糊樹。對分數的改進也是非常有意義的。唯一需要注意的是max(scoreDateTime)包含空註釋行。我想從最近的非空評論中得到日期。 – jmelvin

+0

@jmelvin你可以在'max'裏添加case語句來只考慮帶有註釋的行看更新 – FuzzyTree

+0

完美!不知道這是可能的。模糊樹,你是我的SQL超級英雄! – jmelvin