3

だから私はSQLServer2008に取り組んでいて、このクエリは非常に単純なはずですが、何らかの理由で機能しません。基本的には次のようになります。

SELECT TOP 10
    u.Id                AS "UserId",
    u.CreationDate      AS "Member since",
    AVG(q.Score)        AS "Average Question Rating",  
    COUNT(q.Id)         AS "N. of Questions posted by the agent",
    AVG(a.Score)        AS "Average Answer Rating",  
    COUNT(a.Id)         AS "N. of Answers posted by the agent"
FROM    
        Users u, 
        Answers a, 
        Questions q
WHERE q.OwnerUserId = u.Id
AND a.OwnerUserId = u.Id
GROUP BY u.Id, u.CreationDate

AnswersテーブルまたはQuestionsテーブルのいずれかのみを操作する場合は、すべて問題ありません。しかし、(上記のクエリのように)両方を同時に実行しようとすると、COUNTはまったく機能しません。私が得たのは、COUNT(a.Id)がCOUNT(q.Id)と同一であるということです。そこで、クエリを減らして何が問題なのかを確認しました。他のテーブルを操作するときに、FROM句にQuestionsまたはAnswersテーブルを追加するだけですべてが台無しになっていることに気付きました。

私が見落としていたのはばかばかしいほど些細なことだと確信していますが、それは私を夢中にさせています。誰かが私に何が悪かったのか指摘してくれたらありがたいです。前もって感謝します。

4

4 に答える 4

5

あなたは参加Answersしておらず、Questions正しく集計されていません。との間AnswersQuestions、結果はデカルト積になります(すべてのユーザーに対して、すべての回答がすべての質問と結合されます)

これを修正する最も簡単な方法は、サブクエリで集計を実行することです。

SELECT TOP 10
    u.Id                AS "UserId",
    u.CreationDate      AS "Member since",
    ISNULL((SELECT AVG(Score) FROM Answers   WHERE OwnerUserId = u.Id), 0)
                        AS "Average Question Rating",  
           (SELECT COUNT(*)   FROM Answers   WHERE OwnerUserId = u.Id)        
                        AS "N. of Questions posted by the agent",
    ISNULL((SELECT AVG(Score) FROM Questions WHERE OwnerUserId = u.Id), 0)
                        AS "Average Answer Rating",  
           (SELECT COUNT(*)   FROM Questions WHERE OwnerUserId = u.Id)
                        AS "N. of Answers posted by the agent"
FROM  Users u

または、結合を使用します。

SELECT TOP 10
     u.Id                AS "UserId",
     u.CreationDate      AS "Member since",
     ISNULL(q.a, 0)      AS "Average Question Rating",  
     ISNULL(q.c, 0)      AS "N. of Questions posted by the agent",
     ISNULL(a.a, 0)      AS "Average Answer Rating",  
     ISNULL(a.c, 0)      AS "N. of Answers posted by the agent"
FROM Users u
-- If you LEFT JOIN these tables, you'll get also results for users without
-- questions or answers
LEFT OUTER JOIN (SELECT OwnerUserId, AVG(Score) a, COUNT(*) c 
     FROM Questions GROUP BY OwnerUserId) q
     ON  q.OwnerUserId = u.Id
LEFT OUTER JOIN (SELECT OwnerUserId, AVG(Score) a, COUNT(*) c 
     FROM Answers GROUP BY OwnerUserId) a
     ON  a.OwnerUserId = u.Id

SQL Serverのクエリオプティマイザーが十分にわからないため、どちらが高速になるかはわかりません。最初のソリューションは、SQL Serverで利用可能な場合、スカラーサブクエリキャッシングを利用できますそれ以外の場合、2番目のクエリはネストされていないループを実行する可能性があります。

于 2012-04-23T15:26:47.443 に答える
3

他の場所で述べたように、質問と回答の両方でのユーザーIDの結合は、基本的に2つのテーブル間のユーザーレベルでのデカルト結合を生成します。より良いアプローチは、ユニオンを使用することです。

SELECT TOP 10
    u.Id                AS "UserId",
    u.CreationDate      AS "Member since",
    AVG(q_score)        AS "Average Question Rating",  
    COUNT(q_id)         AS "N. of Questions posted by the agent",
    AVG(a_score)        AS "Average Answer Rating",  
    COUNT(a_id)         AS "N. of Answers posted by the agent"
FROM Users u
JOIN (select OwnerUserId,
             Score        q_score,
             Id           q_id,
             NULL         a_score,
             NULL         a_id
      from Answers
      union all
      select OwnerUserId,
             NULL         q_score,
             NULL         q_id,
             Score        a_score,
             Id           a_id
      from Questions) qa
  ON qa.OwnerUserId = u.Id
GROUP BY u.Id, u.CreationDate
于 2012-04-23T16:04:34.007 に答える
1

DISTINCT Idを数えるだけではうまくいきませんか?

SELECT TOP 10 
    u.Id                         AS "UserId", 
    u.CreationDate               AS "Member since", 
    AVG(q.Score)                 AS "Average Question Rating",   
    COUNT(DISTINCT q.Id)         AS "N. of Questions posted by the agent", 
    AVG(a.Score)                 AS "Average Answer Rating",   
    COUNT(DISTINCT a.Id)          AS "N. of Answers posted by the agent" 
FROM     
        Users u,  
        Answers a,  
        Questions q 
WHERE q.OwnerUserId = u.Id 
AND a.OwnerUserId = u.Id 
GROUP BY u.Id, u.CreationDate 
于 2012-04-23T16:50:26.737 に答える
-1

私の場合は、他のテーブル(回答と質問)に対して明示的な結合を行います。結合しない場合、他のテーブルをどのようにリンクしますか?

SELECT TOP 10
    u.Id                AS "UserId",
    u.CreationDate      AS "Member since",
    AVG(q.Score)        AS "Average Question Rating",  
    COUNT(q.Id)         AS "N. of Questions posted by the agent",
    AVG(a.Score)        AS "Average Answer Rating",  
    COUNT(a.Id)         AS "N. of Answers posted by the agent"
FROM    
        Users u, 
        Answers a, 
        Questions q
WHERE q.OwnerUserId = u.Id
AND a.OwnerUserId = u.Id
GROUP BY u.Id, u.CreationDate

would be

SELECT TOP 10
    u.Id                AS "UserId",
    u.CreationDate      AS "Member since",
    AVG(q.Score)        AS "Average Question Rating",  
    COUNT(q.Id)         AS "N. of Questions posted by the agent",
    AVG(a.Score)        AS "Average Answer Rating",  
    COUNT(a.Id)         AS "N. of Answers posted by the agent"
FROM    
        Users u
JOIN Answers a on u.ID = a.ID (assuming thats how answers and users are linked).
JOIN Questions q on a.ID = q.ID (assuming thats how questions and answers are linked)
WHERE q.OwnerUserId = u.Id
AND a.OwnerUserId = u.Id
GROUP BY u.Id, u.CreationDate
于 2012-04-23T15:25:54.887 に答える