2016-05-04 13 views
0

2つのクエリが別々に正常に動作します。それらが似ているとすれば、私はそれらを1つの実行可能なクエリに統合したいと思います。 where節が似ているので簡単です。しかし、sum、count、min関数はすべて異なる行に適用され、途中で取り込まれます。類似のwhere句で異なる集計関数ターゲットを持つ2つのクエリを統合する

コンテキスト:

  • ユーザーは、スコア(またはレート)の場所とポイントが
  • ユーザーAがユーザーBを参照し、ユーザBが最初
  • ポイントは後に期限切れにスコアを送信したときに、紹介ポイントを得ることができます得ることができます特定の日付
  • 目標は、スコアリングのためのユーザーとその合計点と、特定の場所(地域/国)を参照するための合計点を作成することです。
  • 位置パラメータは、ハードv 'Massachusetts'、 'United States'、およびscoreDateTimeの有効期限のために使用され、両方のselectサブクエリーで残念ながら重複しています。

質問:

がどのようにクエリは、以下の制約を組み合わせるために再編成することができますか?ある日の後に特定の場所から得点のリストから始める方法がなければなりません。唯一の問題は、ユーザーBの最初のスコア日付を取得し、有効期限が過ぎてもユーザーAに参照ポイントを提供することだけです。

select scoring.userId, scoring.points + referring.points as leaderPoints 
from (
    select userId, sum(ratingPoints) as points 
    from  scores s, locations l 
    where s.locationId = l.locationId and 
      l.locationArea = 'Massachusetts' and 
      l.locationCountry = 'United States' and 
      s.scoreDateTime > '2016-04-16 18:50:53.154' and 
      s.userId != 0 
    group by s.userId 
) as scoring 

join (
    select u1.userId, count(*) * 20 as points 
    from users u0 
    join users u1 on u0.userId = u1.userId 
    join users u2 on u2.referredByEmail = u1.emailAddress 
    join scores s on u2.userId = s.userId 
    join locations l on s.locationId = l.locationId 
    where l.locationArea = 'Massachusetts' and 
      l.locationCountry = 'United States' and 
      scoreDateTime = (
       select min(scoreDateTime) 
       from scores 
       where userId = u2.userId 
      ) and 
      scoreDateTime >= '2016-04-16 18:50:53.154' 
    group by u1.userId 
) as referring on scoring.userId = referring.userId 
order by leaderPoints desc 
limit 10; 

答えて

0

おかげスタン・ショウを適用除去するための

修正答えが、私はあなたのクエリが結果をテストするためのMySQL上で動作するように取得することができませんでした。しかし、私は元のクエリでカバーされていない特別なケースに気づいた。ユーザは、自身がスコアを提出していない地域から参照ポイントを得ることができる。新しいユーザーがその地域で得点する限り、そこに参照点があります。

私が使用している最後のクエリは次のとおりです。私は演奏者に見えるように、どこで句を重複してまとめることができませんでした。

select userId, sum(points) as leaderPoints 
from (

    select s.userId, sum(s.ratingPoints) as points 
    from  scores s, locations l 
    where s.locationId = l.locationId and 
      l.locationArea = 'Georgia' and 
      l.locationCountry = 'United States' and 
      s.scoreDateTime >= '2016-04-05 03:00:00.000' and 
      s.userId != 1 
    group by userId 

    union 

    select u1.userId, 20 as points 
    from  users u0, users u1, users u2, scores s, locations l 
    where u0.userId = u1.userId and 
      u2.referredByEmail = u1.emailAddress and 
      u2.userId = s.userId and 
      s.locationId = l.locationId and 
      l.locationArea = 'Georgia' and 
      l.locationCountry = 'United States' and 
      scoreDateTime >= '2016-04-05 03:00:00.000' and 
      scoreDateTime = (
       select min(scoreDateTime) 
       from scores 
       where userId = u2.userId 
      ) 

) as pointsEarned 
group by userId 
order by leaderPoints desc 
limit 10 
order by leaderPoints desc 
limit 100; 
0

これはテストされていないコードですが、そのトリックを行う必要があります。クロス・アプライは可読性を重視していますが、パフォーマンスが低下しますが、これは特にプロセス集中型の問合せではないようです。

ご不明な点がございましたら教えてください。

SELECT U.UserID, 
     ISNULL(SUM(CASE WHEN S.UserID IS NULL THEN 0 ELSE S.ratingPoints END), 0) AS [Rating Points], 
     ISNULL(SUM(CASE WHEN SS.userID IS NULL THEN 0 ELSE 20 END), 0) AS [Referral Points] 
FROM Users U 
LEFT OUTER JOIN scores S 
    ON S.userID = U.userID 
    AND S.scoreDateTime >= '2016-04-16 18:50:53.154' 
LEFT OUTER JOIN locations L 
    ON S.locationID = L.locationID 
    AND L.locationArea = 'Massachusetts' 
    AND L.LocationCountry = 'United States' 
LEFT OUTER JOIN Users U2 
    ON U2.referredByEmail = U.emailAddress 
LEFT OUTER JOIN scores SS 
    ON SS.userID = U2.userID 
LEFT OUTER JOIN locations LL 
    ON SS.locationID = LL.locationID 
    AND LL.locationArea = 'Massachusetts' 
    AND LL.locationCountry = 'United States' 
    AND SS.scoreDateTime >= '2016-04-16 18:50:53.154' 
    AND SS.scoreDateTime = 
     (
      SELECT MIN(scoreDateTime) 
      FROM scores 
      where userID = U2.userID 
     ) 
GROUP BY U.userID 

EDIT:クロス

+0

私はMySQLを使用していますが、明らかにCROSS APPLYは適用されないようです。 locationArea、locationCountry、およびscoreDateTimeの制約が重複しているので、それらを統合することを望んでいました。私がそのスコアのリストの外に到達する唯一の時間は、参照されたユーザーの最初のスコアの日時を得るためのmin(scoreDateTime)です。その日付がカットオフ日付の後にある場合にのみ、紹介ボーナスポイントを授与したいと思います。 – jmelvin

+0

@jmelvin Cross Applyを削除する答えを修正しました。 –

関連する問題