私はこれらの結果があります:
PersonID SUM(PA.Total)
-------------------------
1 75
2 75
3 15
4 15
5 60
6 60
次のようなテーブルで:
PersonID Total
------------------
1 50
2 50
3 10
4 10
5 40
6 40
1 25
2 25
3 5
4 5
5 20
6 20
これらは人によってグループ化されます。今、私はすべての合計の合計から計算された各人のパーセンテージを含む列を追加しようとしています。
たとえば、合計は300なので、次のような結果が必要です。
PersonID SUM(PA.Total) Percentage
--------------------------------------
1 75 25%
2 75 25%
3 15 5%
4 15 5%
5 60 20%
6 60 20%
私はコードをオンラインで見て、次のような修正を思いつきました。
SELECT
P.PersonID, SUM(PA.Total)
SUM(PA.Total) * 100 / [p] AS 'Percentage'
FROM
Person P
JOIN
Package PA ON P.PersonID = PA.PackageFK
CROSS JOIN
(SELECT SUM(PA.[Total]) AS [p]
FROM Package PA) t
GROUP BY
P.PersonID
しかし、既にグループ/合計セクションだけでなく、結合にクロス結合を組み込む方法がわかりません。または、これが完全に正しい線に沿っているかどうか。
任意の助けをいただければ幸いです-SQLフィドル http://sqlfiddle.com/#!9/80f91/2
cross join
は必要ありません。ウィンドウ関数を使用するだけです:
SELECT P.PersonID, SUM(PA.Total),
SUM(PA.Total) * 100.0 / SUM(SUM(PA.Total)) OVER () AS Percentage
FROM Person P JOIN
Package PA
ON P.PersonID = PA.PackageFK
GROUP BY P.PersonID;
このクエリにはJOIN
は必要ないことに注意してください。
SELECT PA.PersonID, SUM(PA.Total),
SUM(PA.Total) * 100.0 / SUM(SUM(PA.Total)) OVER () AS Percentage
FROM Package PA
GROUP BY PA.PersonID;
SQL Serverは整数除算を行います。 10進数を使用してこのような計算を行うため、より理にかなっています。
ここ はSQL Fiddleであり、2つの変更があります。
共通テーブル式を使用できます...
;with cte as(
select P.PersonID,SUM(cast(PA.Total as int))Total from Package PA join Person P on P.PersonID = PA.PackageFK GROUP BY P.PersonID
)
select PersonId,Total,cast (Total * 100 / t.GrandTotal as varchar) + '%' [Percentage] from cte cross join(select SUM(cast(Total as int)) as GrandTotal from Package)t
他の人が言ったように、CTEを使用して問題を解決できます。私の場合は、CROSS JOINを使用せず(特別な理由なし)、CTEを2回行いました。また、ゼロ除算エラーの可能性を防ぐためにNULLIFをスローしました(代わりにNULLが発生します)。
また、PackageテーブルのTotal列は、列の合計または計算を実行するたびに、数値型(特定の「数値」型ではなく、 numbers を保持できる列型)である必要があります。チップオフは数値でなければなりません。
;WITH PersonTotals AS
(
SELECT P.PersonID, SUM(CAST(PA.Total AS MONEY)) Total
FROM Person P
JOIN Package PA ON P.PersonID = PA.PackageFK
GROUP BY P.PersonID
),
GrandTotal AS
(
SELECT SUM(PT.Total) Total
FROM PersonTotals PT
)
SELECT PT.*, (PT.Total / NULLIF((SELECT Total From GrandTotal),0)) * 100 Percentage
FROM PersonTotals PT
以下のコードを試してください
;With cte(PersonID ,Total)
AS
(
SELECT 1 ,75 UNION ALL
SELECT 2 ,75 UNION ALL
SELECT 3 ,15 UNION ALL
SELECT 4 ,15 UNION ALL
SELECT 5 ,60 UNION ALL
SELECT 6 ,60
)
SELECT PersonID,
Total,
CAST(CAST((MAX(total)OVER(partition BY personid ORDER BY total)*100.0/
MaxSum) AS INT)AS VARCHAR(5))+ '%' AS Percentage
FROM (SELECT personid,
total,
stotal,
Max(stotal)
OVER(
ORDER BY stotal DESC) AS MaxSum
FROM (SELECT personid,
total,
Sum(total)
OVER(
ORDER BY personid) AS STotal
FROM Cte)dt
GROUP BY dt.personid,
dt.total,
dt.stotal)dt2
ORDER BY dt2.personid ASC
結果
PersonID Total Percentage
------------------------------
1 75 25%
2 75 25%
3 15 5%
4 15 5%
5 60 20%
6 60 20%