4

私が会社のテーブルを持っているとしましょう:

Company
coID | coName | coCSR

このcoCSRフィールドは、アカウントハンドラテーブルに関連する数値IDです。

AccountHandler
ahID | ahFirstName | ahLastName

注文の表もあります。

Order
orID | orCompanyID | orDate | orValue

今、私が作成する必要があるのは、次のように構造化された出力です。

Company | Account handler | No. of orders | Total of orders

これが私が試したクエリで、エラーが発生します。

SELECT coID, coName, ahFirstName+' '+ahLastName AS CSRName, COUNT(orID) AS numOrders, SUM(orValue) AS totalRevenue
FROM Company
LEFT JOIN AccountHandler ON coCSR = ahID
LEFT JOIN Order ON coID = orCompanyID
WHERE coCSR = 8
AND orDate > getdate() - 365
ORDER BY coName ASC

エラーは次のとおりです。列名'AccountHandler.ahLastName'は、集計関数に含まれておらず、GROUP BY句がないため、ORDERBY句では無効です。

を使用すると、キーワード「WHERE」の近くに誤った構文GROUP BY coIDが表示されます。集計関数のためにに変更すると、集計関数またはGROUPBY句のいずれにも含まれていない他の各列名を削除するように指示するエラーが発生します。WHEREHAVING

認めざるを得ません。最も基本的なSQLコマンド以外のロジックと構文はまだ理解していません。以前に使用したものを適用しようとしているだけで、機能していません。これを機能させるために私を助けてください。さらに良いことに、現時点で機能しない理由を理解するのを手伝ってもらえますか?:)

4

3 に答える 3

5

1 つには、おそらくクエリが欠落FROM Companyしている可能性がありますが、投稿を書いているときに何らかの形で失われた可能性があります。

企業別にデータを集計しているようですね。したがって、会社ごとにグループ化する必要があります。グループ化の試みが失敗した理由として最も可能性が高いのGROUP BYは、間違った場所に配置したためです。の前に置いたと思いますWHEREが、実際にはそれの後(および前ORDER BY)に配置する必要があります。

SELECT
  c.coID,
  c.coName,
  a.ahFirstName + ' ' + a.ahLastName AS CSRName,
  COUNT(o.orID) AS numOrders,
  SUM(o.orValue) AS totalRevenue
FROM Company c
LEFT JOIN AccountHandler a ON c.coCSR = a.ahID
LEFT JOIN [Order] o ON c.coID = o.orCompanyID
WHERE c.coCSR = 8
AND o.orDate > getdate() - 365
GROUP BY ...
ORDER BY c.coName ASC

もう 1 つの問題は、をグループ化するかです。SQL Server では、集計されていないすべての列を で指定する必要がありますGROUP BY。したがって、GROUP BY句は次のようになります。

GROUP BY
  c.coID,
  c.coName,
  a.ahFirstName,
  a.ahLastName

SELECT句で割り当てられたエイリアスによって列を参照できないことに注意してください(例: CSRName)。ただし、対応する列の代わりに式を使用できますがahFirstName+' '+ahLastName、この特定の状況では何の違いもありません。

SELECTこのクエリに集計されていない列をさらに追加する必要がある場合は、との両方に追加する必要がありますGROUP BY。ある時点で、これは少し面倒になるかもしれません。代わりに次のことを試すことをお勧めします。

SELECT
  c.coID,
  c.coName,
  a.ahFirstName + ' ' + a.ahLastName AS CSRName,
  ISNULL(o.numOrders,    0) AS numOrders,
  ISNULL(o.totalRevenue, 0) AS totalRevenue
FROM Company c
LEFT JOIN AccountHandler a ON c.coCSR = a.ahID
LEFT JOIN (
  SELECT
    orCompanyID,
    COUNT(orID)  AS numOrders,
    SUM(orValue) AS totalRevenue
  FROM [Order]
  GROUP BY
    orCompanyID
  WHERE orDate > getdate() - 365
) o ON c.coID = o.orCompanyID
WHERE c.coCSR = 8
ORDER BY c.coName ASC

つまり、集計はOrderテーブルのみで行われます。次に、集計された行セットが他のテーブルに結合されます。そのレベルでのグループ化はもはや必要ないため、属性を追加することを心配することなく、Companyまたはから出力にさらに多くの属性をプルできるようになりました。AccountHandlerGROUP BY

于 2012-06-22T21:04:35.787 に答える
1

以下のようにクエリを変更できますか?追加MaxしてGroup By Clause

SELECT 
        MAX(C.coID), 
        C.coName, 
        MAX(AH.ahFirstName+' '+ AH.ahLastName ) AS CSRName, 
        COUNT(O.orID) AS numOrders, 
        SUM(O.orValue) AS totalRevenue
From Company C
LEFT JOIN AccountHandler AH ON C.coCSR = AH.ahID
LEFT JOIN Order O ON C.coID = O.orCompanyID
WHERE   C.coCSR = 8 AND 
        O.orDate > getdate() - 365
Group by C.coName
ORDER BY C.coName ASC

私のおすすめ

選択した列名にはエイリアスを使用する必要があります

于 2012-06-22T19:08:32.013 に答える
0
SELECT 
      --<<<non aggregate section of SELECT clause
     coID   
     , coName
     , [CSRName] = CONVERT(VARCHAR(100),ahFirstName + ' ' + ahLastName) 

      --<<<aggregate section of SELECT clause
     , [numOrders] = COUNT(orID)
     , [totalRevenue] = SUM(orValue) 
FROM   --<<<<<<sql is not too happy without FROM
    Company c
    LEFT JOIN AccountHandler a
       ON coCSR = ahID
    LEFT JOIN Order o
       ON coID = orCompanyID
WHERE coCSR = 8
   AND orDate > getdate() - 365
GROUP BY
     coID   
     , coName
     , CONVERT(VARCHAR(100),ahFirstName + ' ' + ahLastName) --<<<<looks like aggregate but is just text manipulation
ORDER BY coName ASC

2つの集計関数があります; aCOUNTSUM; これは、いくつかのグループ化を行う必要があることを意味し、一般的な経験則はGROUP BY、select句の非集約セクションです。

OPの非常に大きな問題は、2つのテーブルを結合するときに、どのフレーバー(LEFT、RIGHT、OUTER、INNER、CROSS)でも、FROM句に含める必要があり、結合の両側にテーブルを指定する必要があることです。

次に、複数のテーブルを結合する場合は、各テーブルにエイリアスを使用することをお勧めします。小文字を1つ使用しました。c / o/a。列名を確認しても、すべての列に一意の名前が付けられているため、これらは必要ない場合があります。

于 2012-06-22T22:19:53.620 に答える