web-dev-qa-db-ja.com

T-SQLクエリ-列の行のSUM()を新しい行列にAVERAGE()する方法

求められるのは、各生徒の平均点数を、点数の合計を数で割ったもので構成することです。

AVG関数は、垂直方向の平均を列方向ではなく水平方向で取得する集計関数であるため、クエリはこれをどのように行う必要がありますか。これを達成するためのエレガントな方法はありますか?クエリ?

スクリーンショットで以下のクエリについて詳しく説明してもらえますか、それが機能するように変更してください。簡単な合計/カウントなしでAVGとCOUNT()のみを使用してこれを行うエレガントな方法はありますか?

私はスクリーンショットに次の解決策を加えてさらに拡張し、うまくいくようにしましたが、私にとっては正しくないようです:

enter image description here

以下のコードを見つけてください(合計および合計フィールド数による除算としての私の自明な解決策):


USE [Students]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Students](
 [StudentID] [int] NOT NULL,
 [StudentName] [nchar](100) NOT NULL,
 [StudentSurname] [nchar](100) NOT NULL,
 [Biology] [decimal](3, 2) NOT NULL,
 [Maths] [decimal](3, 2) NOT NULL,
 [Geography] [decimal](3, 2) NOT NULL,
CONSTRAINT [PK_Students] PRIMARY KEY CLUSTERED 
(
 [StudentID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

GO
INSERT [dbo].[Students] ([StudentID], [StudentName], [StudentSurname], [Biology], [Maths], [Geography]) VALUES (1, N'Mike                                                                                                ', N'Manson                                                                                              ', CAST(2.00 AS Decimal(3, 2)), CAST(2.00 AS Decimal(3, 2)), CAST(1.00 AS Decimal(3, 2)))
INSERT [dbo].[Students] ([StudentID], [StudentName], [StudentSurname], [Biology], [Maths], [Geography]) VALUES (2, N'Timo                                                                                                ', N'Torn                                                                                                ', CAST(1.00 AS Decimal(3, 2)), CAST(2.00 AS Decimal(3, 2)), CAST(4.00 AS Decimal(3, 2)))
INSERT [dbo].[Students] ([StudentID], [StudentName], [StudentSurname], [Biology], [Maths], [Geography]) VALUES (3, N'Jeffrey                                                                                             ', N'Jones                                                                                               ', CAST(1.00 AS Decimal(3, 2)), CAST(3.00 AS Decimal(3, 2)), CAST(4.00 AS Decimal(3, 2)))
GO

SELECT * FROM Students;

SELECT
(SELECT Biology + Maths + Geography)/3 AS Mark_average
FROM Students;

上記のクエリの出力は次のとおりです。

Mark_average
1.666666
2.333333
2.666666

結果を取得するための代替のよりエレガントで洗練された方法(SUM()関数のAVG()を使用するサブクエリなど、スクリーンショットにあるものと同様)はありますか?

よろしくお願いします!

1
query_question

別のソリューションを探している場合は、常にデータのピボットを解除し、集計してから、ソーステーブルに結合することができます。例を示します。

また、サンプルのテーブルとデータを含めて作業するのがとても簡単になり、本当にありがとうございました。

;WITH CTE_Unpivot AS
    (
    SELECT StudentID, MarkSubject, Mark 
    FROM dbo.Students AS S
        UNPIVOT (Mark FOR MarkSubject IN (Biology, Maths, [Geography])) AS upvt
    )
, CTE_Average AS
    (
    SELECT StudentID, AVG(Mark) AS StudentAverage
    FROM CTE_Unpivot AS U
    GROUP BY StudentID 
    )
SELECT S.StudentID
    , S.StudentName
    , S.StudentSurname
    , S.Biology
    , S.Maths
    , S.[Geography]
    , A.StudentAverage
FROM dbo.Students AS S
    LEFT OUTER JOIN CTE_Average AS A ON S.StudentID = A.StudentID

これは、単にフィールドを加算して分割するよりも効率が悪いことを指摘する必要があると感じています。このようなデータを操作すると、データが複数回影響を受けるため、tempdbに流出してCPUコストが高くなる可能性が高くなります。おそらく無視できますが、まだです。

1
Jonathan Fite