2

ダッシュボードをコーディングしていて、Microsoft SQL Server からデータを引き出す必要があります。

簡単な例として、3 つのテーブル、1 つのマスター カテゴリ テーブル、およびプライマリ/外部キー関係 (青と緑の値テーブル) を介してカテゴリ テーブルにリンクされた値を含む 2 つのテーブルがあります。

Microsoft SQL Sever (t-sql) を使用して、2 つの値テーブルの値を、カテゴリ テーブルにある共通カテゴリでグループ化して合計 (合計) したいと考えています。

カテゴリー表

CategoryID (PK) | CategoryName
1               | Square
2               | Circle

ブルーテーブル

BlueID (PK) | CategoryID (FK) | BlueValue | BlueMonth | BlueYear
1           | 1               | 10        | 6         | 2012
2           | 1               | 20        | 12        | 2012
3           | 2               | 5         | 6         | 2012
4           | 2               | 9         | 12        | 2012
5           | 1               | 12        | 6         | 2013
6           | 1               | 21        | 12        | 2013
7           | 2               | 4         | 6         | 2013
8           | 2               | 8         | 12        | 2013

グリーンテーブル

GreenID (PK)| CategoryID (FK) | GreenValue| GreenMonth| GreenYear
1           | 1               | 3         | 6         | 2012
2           | 1               | 6         | 12        | 2012
3           | 2               | 2         | 6         | 2012
4           | 2               | 7         | 12        | 2012
5           | 1               | 2         | 6         | 2013
6           | 1               | 5         | 12        | 2013
7           | 2               | 4         | 6         | 2013
8           | 2               | 8         | 12        | 2013

次の SQL を使用すると、期待どおりの結果が得られます。

SELECT
    [Category].[CategoryName],
    SUM([Green].[GreenValue]) AS [GreenTotal]
FROM
    [Category]
LEFT JOIN
    [Green] ON [Category].[CategoryID] = [Green].[CategoryID]
GROUP BY
    [Category].[CategoryName]

結果:

CategoryName | GreenTotal
Square       | 16
Triangle     | 21

ただし、Blue テーブルを追加して、BlueValue の合計も取得しようとすると、明らかに正しくない T-SQL によって予期しない結果が得られます。

SELECT
    [Category].[CategoryName],
    SUM([Green].[GreenValue]) AS [GreenTotal],
    SUM([Blue].[BlueValue]) AS [BlueTotal]
FROM
    [Category]
LEFT JOIN
    [Green] ON [Category].[CategoryID] = [Green].[CategoryID]
LEFT JOIN
    [Blue] ON [Category].[CategoryID] = [Blue].[CategoryID]
GROUP BY
    [Category].[CategoryName]

不正確な結果:

CategoryName | GreenTotal | BlueTotal
Square       | 64         | 252
Triangle     | 84         | 104

結果はすべて、各カテゴリの各値テーブルの行の合計数である 4 倍になっているように見えます。

私は次の結果を見ることを目指しています。

CategoryName | GreenTotal | BlueTotal
Square       | 16         | 63
Triangle     | 21         | 26

誰かが私が間違っていることを教えてくれたら、私は大喜びしますか?

ありがとう、マーク。

4

5 に答える 5

4

私の意見では、このようなことは APPLY で行うのが最善です。パフォーマンスが速く、使いやすく、クエリにバリエーションがある場合でも簡単に制御できます。

いいえ:

SELECT C.[CategoryName], G.[GreenTotal], B.[BlueTotal]
FROM [Category] C
OUTER APPLY (SELECT SUM([GreenValue]) AS [GreenTotal] FROM [Green] WHERE [CategoryID] = C.CategoryID) G
OUTER APPLY (SELECT SUM([BlueValue]) AS [BlueTotal] FROM [Blue] WHERE [CategoryID] = C.CategoryID) B
于 2013-11-13T14:31:40.233 に答える
2

あなたが得ているのはデカルト積です。グループ化を削除してデータを調べると、この効果を確認できます。

例えば; 緑のテーブルに 2 つの行が含まれ、青のテーブルに 4 つの行が含まれている場合、結合によって合計 8 つのレコードが返されます。

問題を解決するには、まあ、あと少しです。あなたはすべての適切なピースを手に入れましたが、それらを完全に組み合わせていません.

次のクエリが緑の正しい結果を返すと仮定します。

SELECT CategoryID
     , Sum(GreenValue) As GreenTotal
FROM   Green
GROUP
    BY CategoryID

青の結果は、同じ方法で取得できます。

SELECT CategoryID
     , Sum(BueValue) As BlueTotal
FROM   Blue
GROUP
    BY CategoryID

正しい 2 つの異なる結果が得られたので、これらの結果をカテゴリ テーブルに結合する必要があります。

SELECT Category.CategoryName
     , GreenSummary.GreenTotal
     , BlueSummary.BlueTotal
FROM   Category
 LEFT
  JOIN (    
        SELECT CategoryID
             , Sum(GreenValue) As GreenTotal
        FROM   Green
        GROUP
            BY CategoryID
       ) As GreenSummary
    ON GreenSummary.CategoryID = Category.CategoryID
 LEFT
  JOIN (    
        SELECT CategoryID
             , Sum(BlueValue) As BlueTotal
        FROM   Blue
        GROUP
            BY CategoryID
       ) As BlueSummary
    ON BlueSummary.CategoryID = Category.CategoryID
于 2013-11-13T14:25:19.310 に答える
0

合計テーブルごとにクエリを作成します。カテゴリ別にグループ化し、合計列を作成して列 ID を追加します。

次に、このクエリをサブクエリとして使用し、メイン テーブルとの左外部結合を作成します。これにより、期待どおりの結果が得られ、合計が得られない場合は null 値になる可能性があります。isnull 関数を使用して、null 値を 0 に変換できます。

于 2013-11-13T14:23:57.223 に答える