sql 服务器中的多枢轴
Multi pivot in sql server
以下是我的 sql 服务器的查询:
SELECT t.type ,
t.fmsales ,
t.indussales
FROM ( SELECT CASE WHEN ( GROUPING(mti.type) = 1 ) THEN 'ALL'
ELSE ISNULL(mti.Type, 'UNKNOWN')
END AS type ,
SUM(ISNULL(mti.SALES_THIS + mti.SWITCHIN_THIS, 0)) fmsales ,
SUM(ISNULL(mti.SALES_ALL + mti.SWITCHIN_ALL, 0)) indussales
FROM dbo.IMonthly_trigger_Industry mti ,
dbo.RMMappingDb rm ,
dbo.EmployeeDB ed
WHERE ed.EmployeeCode = 1217
AND rm.BranchName = mti.Branch
AND rm.ARNCode = mti.BROKER
AND rm.EmployeeCode = ed.EmployeeCode
AND mti.BROKER_NAME LIKE '%Pvt Limited%'
GROUP BY mti.Type
WITH CUBE
) t
WHERE t.type IS NOT NULL
GROUP BY t.type ,
t.fmsales ,
t.indussales;
结果是这样的:
我想转置这个结果集,使行变成列,列变成行。我之前使用了 pivot 方法,其中我只有一列来进行聚合,但这里是不同的。有人可以帮助我实现这一目标吗?
结果应该是这样的:
我怎样才能做到这一点?我尝试使用数据透视表,因为数据透视表只允许在一列上进行聚合,所以我无法获得预期的结果。任何帮助深表感谢。提前致谢。
您可以使用 PIVOT
和 UNPIVOT
的组合来执行此操作,如下所示:
select *
from
(
select * from t
) s
unpivot
(
val for product in ([fmsales],[indussales])
)up
pivot
(
max(val) for type in ([ALL],[CASH],[DEBIT],[EQUITY])
)p
演示 sql fiddle link:http://sqlfiddle.com/#!6/381f7/4
解释:
首先,我们使用 UNPIVOT
获取 fmsales
、indussales
列名作为行数据,然后 PIVOT
覆盖 type
列。
在此处查看 UNPIVOT
的中间结果:
您可以使用 UNION ALL
首先对数据进行逆透视,然后使用条件聚合进行透视:
WITH Cte AS(
--Your original query here
SELECT 'ALL' AS type, 0 AS fmsales, 82.1 AS indussales UNION ALL
SELECT 'CASH' AS type, 0 AS fmsales, 0 AS indussales UNION ALL
SELECT 'DEBT' AS type, 0 AS fmsales, 62 AS indussales UNION ALL
SELECT 'EQUITY' AS type, 0 AS fmsales, 20.1 AS indussales
),
CteUnpivot AS(
SELECT 'fmsales' AS products, 'ALL' AS type, fmsales AS val FROM Cte WHERE type = 'ALL' UNION ALL
SELECT 'fmsales' AS products, 'CASH' AS type, fmsales AS val FROM Cte WHERE type = 'CASH' UNION ALL
SELECT 'fmsales' AS products, 'DEBT' AS type, fmsales AS val FROM Cte WHERE type = 'DEBT' UNION ALL
SELECT 'fmsales' AS products, 'EQUITY' AS type, fmsales AS val FROM Cte WHERE type = 'EQUITY'UNION ALL
SELECT 'indussales' AS products, 'ALL' AS type, indussales AS val FROM Cte WHERE type = 'ALL' UNION ALL
SELECT 'indussales' AS products, 'CASH' AS type, indussales AS val FROM Cte WHERE type = 'CASH' UNION ALL
SELECT 'indussales' AS products, 'DEBT' AS type, indussales AS val FROM Cte WHERE type = 'DEBT' UNION ALL
SELECT 'indussales' AS products, 'EQUITY' AS type, indussales AS val FROM Cte WHERE type = 'EQUITY'
)
SELECT
[ALL] = SUM(CASE WHEN type = 'ALL' THEN val ELSE 0 END),
CASH = SUM(CASE WHEN type = 'CASH' THEN val ELSE 0 END),
DEBT = SUM(CASE WHEN type = 'DEBT' THEN val ELSE 0 END),
EQUITY = SUM(CASE WHEN type = 'EQUITY' THEN val ELSE 0 END)
FROM CteUnpivot
GROUP BY products
当首先 unpivoting
数据然后 pivoting
结果时,您可以通过标准技巧做到这一点:
DECLARE @t TABLE(type NVARCHAR(MAX), fmsales MONEY, indussales MONEY)
INSERT INTO @t VALUES
('ALL', 0, 82.1),
('CASH', 0, 0),
('DEBT', 0, 62),
('EQUITY', 0, 20.1)
SELECT * FROM @t
UNPIVOT(a FOR products IN([fmsales],[indussales]))u
PIVOT (MAX(a) FOR type IN([ALL],[CASH],[DEBT],[EQUITY]))p
输出:
products ALL CASH DEBT EQUITY
fmsales 0.00 0.00 0.00 0.00
indussales 82.10 0.00 62.00 20.10
为了将此应用于您的查询,您可以使用 common table expressions(CTE)
,例如:
;WITH cte AS(
SELECT t.type ,
t.fmsales ,
t.indussales
FROM ( SELECT CASE WHEN ( GROUPING(mti.type) = 1 ) THEN 'ALL'
ELSE ISNULL(mti.Type, 'UNKNOWN')
END AS type ,
SUM(ISNULL(mti.SALES_THIS + mti.SWITCHIN_THIS, 0)) fmsales ,
SUM(ISNULL(mti.SALES_ALL + mti.SWITCHIN_ALL, 0)) indussales
FROM dbo.IMonthly_trigger_Industry mti ,
dbo.RMMappingDb rm ,
dbo.EmployeeDB ed
WHERE ed.EmployeeCode = 1217
AND rm.BranchName = mti.Branch
AND rm.ARNCode = mti.BROKER
AND rm.EmployeeCode = ed.EmployeeCode
AND mti.BROKER_NAME LIKE '%Pvt Limited%'
GROUP BY mti.Type
WITH CUBE
) t
WHERE t.type IS NOT NULL
GROUP BY t.type ,
t.fmsales ,
t.indussales
)
SELECT * FROM cte
UNPIVOT(a FOR products IN([fmsales],[indussales]))u
PIVOT (MAX(a) FOR type IN([ALL],[CASH],[DEBT],[EQUITY]))p
我们可以在交叉应用中完成,但已经晚了
DECLARE @t TABLE(type NVARCHAR(MAX), fmsales MONEY, indussales MONEY)
INSERT INTO @t VALUES
('ALL', 0, 82.1),
('CASH', 0, 0),
('DEBT', 0, 62),
('EQUITY', 0, 20.1)
select col As Products,[ALL],[Cash],[Debt],[Equity],
from (select type,col,val from @t
CROSS APPLY (values(fmsales, 'fmsales'),( indussales, 'indussales'))CS(col,val))K
PIVOT(MAX(val)
FOR TYPE IN
([ALL],[Cash],[Debt],[Equity]))P
以下是我的 sql 服务器的查询:
SELECT t.type ,
t.fmsales ,
t.indussales
FROM ( SELECT CASE WHEN ( GROUPING(mti.type) = 1 ) THEN 'ALL'
ELSE ISNULL(mti.Type, 'UNKNOWN')
END AS type ,
SUM(ISNULL(mti.SALES_THIS + mti.SWITCHIN_THIS, 0)) fmsales ,
SUM(ISNULL(mti.SALES_ALL + mti.SWITCHIN_ALL, 0)) indussales
FROM dbo.IMonthly_trigger_Industry mti ,
dbo.RMMappingDb rm ,
dbo.EmployeeDB ed
WHERE ed.EmployeeCode = 1217
AND rm.BranchName = mti.Branch
AND rm.ARNCode = mti.BROKER
AND rm.EmployeeCode = ed.EmployeeCode
AND mti.BROKER_NAME LIKE '%Pvt Limited%'
GROUP BY mti.Type
WITH CUBE
) t
WHERE t.type IS NOT NULL
GROUP BY t.type ,
t.fmsales ,
t.indussales;
结果是这样的:
我想转置这个结果集,使行变成列,列变成行。我之前使用了 pivot 方法,其中我只有一列来进行聚合,但这里是不同的。有人可以帮助我实现这一目标吗?
结果应该是这样的:
我怎样才能做到这一点?我尝试使用数据透视表,因为数据透视表只允许在一列上进行聚合,所以我无法获得预期的结果。任何帮助深表感谢。提前致谢。
您可以使用 PIVOT
和 UNPIVOT
的组合来执行此操作,如下所示:
select *
from
(
select * from t
) s
unpivot
(
val for product in ([fmsales],[indussales])
)up
pivot
(
max(val) for type in ([ALL],[CASH],[DEBIT],[EQUITY])
)p
演示 sql fiddle link:http://sqlfiddle.com/#!6/381f7/4
解释:
首先,我们使用 UNPIVOT
获取 fmsales
、indussales
列名作为行数据,然后 PIVOT
覆盖 type
列。
在此处查看 UNPIVOT
的中间结果:
您可以使用 UNION ALL
首先对数据进行逆透视,然后使用条件聚合进行透视:
WITH Cte AS(
--Your original query here
SELECT 'ALL' AS type, 0 AS fmsales, 82.1 AS indussales UNION ALL
SELECT 'CASH' AS type, 0 AS fmsales, 0 AS indussales UNION ALL
SELECT 'DEBT' AS type, 0 AS fmsales, 62 AS indussales UNION ALL
SELECT 'EQUITY' AS type, 0 AS fmsales, 20.1 AS indussales
),
CteUnpivot AS(
SELECT 'fmsales' AS products, 'ALL' AS type, fmsales AS val FROM Cte WHERE type = 'ALL' UNION ALL
SELECT 'fmsales' AS products, 'CASH' AS type, fmsales AS val FROM Cte WHERE type = 'CASH' UNION ALL
SELECT 'fmsales' AS products, 'DEBT' AS type, fmsales AS val FROM Cte WHERE type = 'DEBT' UNION ALL
SELECT 'fmsales' AS products, 'EQUITY' AS type, fmsales AS val FROM Cte WHERE type = 'EQUITY'UNION ALL
SELECT 'indussales' AS products, 'ALL' AS type, indussales AS val FROM Cte WHERE type = 'ALL' UNION ALL
SELECT 'indussales' AS products, 'CASH' AS type, indussales AS val FROM Cte WHERE type = 'CASH' UNION ALL
SELECT 'indussales' AS products, 'DEBT' AS type, indussales AS val FROM Cte WHERE type = 'DEBT' UNION ALL
SELECT 'indussales' AS products, 'EQUITY' AS type, indussales AS val FROM Cte WHERE type = 'EQUITY'
)
SELECT
[ALL] = SUM(CASE WHEN type = 'ALL' THEN val ELSE 0 END),
CASH = SUM(CASE WHEN type = 'CASH' THEN val ELSE 0 END),
DEBT = SUM(CASE WHEN type = 'DEBT' THEN val ELSE 0 END),
EQUITY = SUM(CASE WHEN type = 'EQUITY' THEN val ELSE 0 END)
FROM CteUnpivot
GROUP BY products
当首先 unpivoting
数据然后 pivoting
结果时,您可以通过标准技巧做到这一点:
DECLARE @t TABLE(type NVARCHAR(MAX), fmsales MONEY, indussales MONEY)
INSERT INTO @t VALUES
('ALL', 0, 82.1),
('CASH', 0, 0),
('DEBT', 0, 62),
('EQUITY', 0, 20.1)
SELECT * FROM @t
UNPIVOT(a FOR products IN([fmsales],[indussales]))u
PIVOT (MAX(a) FOR type IN([ALL],[CASH],[DEBT],[EQUITY]))p
输出:
products ALL CASH DEBT EQUITY
fmsales 0.00 0.00 0.00 0.00
indussales 82.10 0.00 62.00 20.10
为了将此应用于您的查询,您可以使用 common table expressions(CTE)
,例如:
;WITH cte AS(
SELECT t.type ,
t.fmsales ,
t.indussales
FROM ( SELECT CASE WHEN ( GROUPING(mti.type) = 1 ) THEN 'ALL'
ELSE ISNULL(mti.Type, 'UNKNOWN')
END AS type ,
SUM(ISNULL(mti.SALES_THIS + mti.SWITCHIN_THIS, 0)) fmsales ,
SUM(ISNULL(mti.SALES_ALL + mti.SWITCHIN_ALL, 0)) indussales
FROM dbo.IMonthly_trigger_Industry mti ,
dbo.RMMappingDb rm ,
dbo.EmployeeDB ed
WHERE ed.EmployeeCode = 1217
AND rm.BranchName = mti.Branch
AND rm.ARNCode = mti.BROKER
AND rm.EmployeeCode = ed.EmployeeCode
AND mti.BROKER_NAME LIKE '%Pvt Limited%'
GROUP BY mti.Type
WITH CUBE
) t
WHERE t.type IS NOT NULL
GROUP BY t.type ,
t.fmsales ,
t.indussales
)
SELECT * FROM cte
UNPIVOT(a FOR products IN([fmsales],[indussales]))u
PIVOT (MAX(a) FOR type IN([ALL],[CASH],[DEBT],[EQUITY]))p
我们可以在交叉应用中完成,但已经晚了
DECLARE @t TABLE(type NVARCHAR(MAX), fmsales MONEY, indussales MONEY)
INSERT INTO @t VALUES
('ALL', 0, 82.1),
('CASH', 0, 0),
('DEBT', 0, 62),
('EQUITY', 0, 20.1)
select col As Products,[ALL],[Cash],[Debt],[Equity],
from (select type,col,val from @t
CROSS APPLY (values(fmsales, 'fmsales'),( indussales, 'indussales'))CS(col,val))K
PIVOT(MAX(val)
FOR TYPE IN
([ALL],[Cash],[Debt],[Equity]))P