私はSQLが初めてです。
このようなテーブルがあります:
ID | TeamID | UserID | ElementID | PhaseID | Effort
-----------------------------------------------------
1 | 1 | 1 | 3 | 5 | 6.74
2 | 1 | 1 | 3 | 6 | 8.25
3 | 1 | 1 | 4 | 1 | 2.23
4 | 1 | 1 | 4 | 5 | 6.8
5 | 1 | 1 | 4 | 6 | 1.5
そして、私はこのようなデータを取得するように言われました
ElementID | PhaseID1 | PhaseID5 | PhaseID6
--------------------------------------------
3 | NULL | 6.74 | 8.25
4 | 2.23 | 6.8 | 1.5
PIVOT機能を使用する必要があることを理解しています。しかし、それを明確に理解することはできません。誰かが上記のケースでそれを説明できればとても助かります。
PIVOT
は、1つの列から複数の列にデータを回転させるために使用されます。
ここでの例は、静的ピボットです。これは、回転する列をハードコーディングすることを意味します。
create table temp
(
id int,
teamid int,
userid int,
elementid int,
phaseid int,
effort decimal(10, 5)
)
insert into temp values (1,1,1,3,5,6.74)
insert into temp values (2,1,1,3,6,8.25)
insert into temp values (3,1,1,4,1,2.23)
insert into temp values (4,1,1,4,5,6.8)
insert into temp values (5,1,1,4,6,1.5)
select elementid
, [1] as phaseid1
, [5] as phaseid5
, [6] as phaseid6
from
(
select elementid, phaseid, effort
from temp
) x
pivot
(
max(effort)
for phaseid in([1], [5], [6])
)p
SQLデモ が動作バージョンです。
これは、列のリストを動的に作成し、PIVOTを実行する動的PIVOTでも実行できます。
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.phaseid)
FROM temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT elementid, ' + @cols + ' from
(
select elementid, phaseid, effort
from temp
) x
pivot
(
max(effort)
for phaseid in (' + @cols + ')
) p '
execute(@query)
両方の結果:
ELEMENTID PHASEID1 PHASEID5 PHASEID6
3 Null 6.74 8.25
4 2.23 6.8 1.5
これらは非常に基本的なピボットの例です。
SQL SERVER – PIVOTおよびUNPIVOTテーブルの例
製品表の上記リンクの例:
SELECT PRODUCT, FRED, KATE
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT (SUM(QTY) FOR CUST IN (FRED, KATE)) AS pvt
ORDER BY PRODUCT
レンダリング:
PRODUCT FRED KATE
--------------------
BEER 24 12
MILK 3 1
SODA NULL 6
VEG NULL 5
同様の例はブログ投稿にあります SQL Serverのピボットテーブル。簡単なサンプル
私はこれに慣れていなかったので、素敵な投稿を作成しました...私の問題は、集計を正しく適用する方法を理解することでした。ここに私の投稿があります: http://jaider.net/posts/ 1176-pivot-in-sql-server-correct-aggregated-results /
@bluefeetソリューションでは、elementid
が「見えない」Group By
のキー列であることに注意することが重要です。さらに、elementid
を置き換えるか、userid
などの列を追加できます。
SELECT <non-pivoted column>,
[first pivoted column] AS <column name>,
[second pivoted column] AS <column name>,
...
[last pivoted column] AS <column name>
FROM
(<SELECT query that produces the data>)
AS <alias for the source query>
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
<optional ORDER BY clause>;
USE AdventureWorks2008R2 ;
GO
SELECT DaysToManufacture, AVG(StandardCost) AS AverageCost
FROM Production.Product
GROUP BY DaysToManufacture;
DaysToManufacture AverageCost
0 5.0885
1 223.88
2 359.1082
4 949.4105
-- Pivot table with one row and five columns
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days,
[0], [1], [2], [3], [4]
FROM
(SELECT DaysToManufacture, StandardCost
FROM Production.Product) AS SourceTable
PIVOT
(
AVG(StandardCost)
FOR DaysToManufacture IN ([0], [1], [2], [3], [4])
) AS PivotTable;
Here is the result set.
Cost_Sorted_By_Production_Days 0 1 2 3 4
AverageCost 5.0885 223.88 359.1082 NULL 949.4105
ここに追加するものがありますが、誰も言及していません。
pivot
関数は、ソースに3つの列がある場合に機能します。1つはaggregate
用で、1つはfor
で列として広がり、1つはrow
分布のピボットとして機能します。製品の例では、QTY, CUST, PRODUCT
です。
ただし、ソースにさらに列がある場合、追加列ごとの一意の値に基づいて、ピボットごとに1行ではなく、結果が複数行に分割されます(Group By
は単純なクエリで行うように)。
この例を参照してください。iveは、ソーステーブルにタイムスタンプ列を追加しました。
その影響を確認してください:
SELECT CUST, MILK
FROM Product
-- FROM (SELECT CUST, Product, QTY FROM PRODUCT) p
PIVOT (
SUM(QTY) FOR PRODUCT IN (MILK)
) AS pvt
ORDER BY CUST
これを修正するために、上記の誰もが行ったように、サブクエリをソースとしてプルすることができます-3列のみ(これは常にシナリオで機能するとは限りません。where
条件を配置する必要がある場合タイムスタンプ用)。
2番目の解決策は、group by
を使用して、ピボットされた列の値の合計を再度実行することです。
SELECT
CUST,
sum(MILK) t_MILK
FROM Product
PIVOT (
SUM(QTY) FOR PRODUCT IN (MILK)
) AS pvt
GROUP BY CUST
ORDER BY CUST
GO
互換性エラーを設定するには
ピボット機能を使用する前にこれを使用してください
ALTER DATABASE [dbname] SET COMPATIBILITY_LEVEL = 100