我正在尝试学习SQL Server 2008 R2中的ROLLUP
和GROUPING SETS
运算符。我的表看起来像这样:
+-------+---------+------------+------+-------+----------+------+ | EmpID | EmpName | StartDate | Type | Units | Account | Dist | +-------+---------+------------+------+-------+----------+------+ | 11111 | Alice | 2015-09-04 | SD20 | 0.500 | 560.2200 | 100 | | 11111 | Alice | 2015-09-08 | CCS | 1.330 | 9P0.6010 | 38 | | 11111 | Alice | 2015-09-08 | CCS | 2.170 | 010.9055 | 62 | | 11111 | Alice | 2015-09-10 | SD20 | 0.500 | LP0.3002 | 100 | | 11111 | Alice | 2015-09-14 | SD20 | 0.500 | LP0.3002 | 100 | | 11111 | Alice | 2015-09-17 | SD20 | 1.000 | LP0.P303 | 100 | | 11111 | Alice | 2015-09-18 | SD20 | 1.000 | 600.2200 | 100 | | 11111 | Alice | 2015-09-24 | SD20 | 1.000 | LP0.3002 | 100 | | 11111 | Alice | 2015-09-25 | SD20 | 1.000 | LP0.3002 | 100 | | 11111 | Alice | 2015-09-29 | SD20 | 1.000 | LP0.3002 | 100 | | 33333 | Carol | 2015-09-03 | SD20 | 1.000 | 9P0.PP10 | 100 | | 33333 | Carol | 2015-09-04 | SD20 | 0.200 | 600.6P62 | 20 | | 33333 | Carol | 2015-09-04 | SD20 | 0.800 | 600.6P62 | 80 | | 33333 | Carol | 2015-09-25 | SD20 | 1.000 | P50.2100 | 100 | +-------+---------+------------+------+-------+----------+------+
我希望EmpID和EmpName每个员工显示一次,单位按类型小计,并按EmpID,Type,Account排序,如下:
+-------+---------+----------------+-------+----------+ | EmpID | EmpName | Type | Units | Account | +-------+---------+----------------+-------+----------+ | 11111 | Alice | | | | | | | CCS | 2.17 | 010.9055 | | | | CCS | 1.33 | 9P0.6010 | | | | Subtotal | 3.5 | | | | | SD20 | 0.5 | 560.2200 | | | | SD20 | 1 | 600.2200 | | | | SD20 | 4 | LP0.3002 | | | | SD20 | 1 | LP0.P303 | | | | Subtotal | 6.5 | | | 33333 | Carol | | | | | | | SD20 | 1 | 600.6P62 | | | | SD20 | 1 | 9P0.PP10 | | | | SD20 | 1 | P50.2100 | | | | Subtotal | 3 | | +-------+---------+----------------+-------+----------+
这是我的查询
select
case
when Account is null and Type is null then cast(EmpID as varchar(10))
else ''
end SubEIN,
case
when Account is null and Type is null then EmpName
else ''
end SubName,
case
when Account is null and Type is not null then 'Subtotal:'
else isnull(Type, '')
end Type,
case
when Account is null and Type is null then ''
else cast(Units as varchar(10))
end Units,
isnull(Account, '')
from (
select EmpID, EmpName, Type, sum(Units) AS Units, Account
from mytable
group by grouping sets ((EmpID, EmpName), (EmpID, EmpName, Type), (EmpID, EmpName, Account, Type))
) x
order by x.EmpName, x.Type, x.Units, x.Account
我可以使用ROLLUP
和/或GROUPING SETS
运算符来获取我想要的内容而不是所有CASE
个表达式吗?
答案 0 :(得分:0)
我相信GROUP BY WITH CUBE运算符会让你接近最终目标。使用此方法,您可以选择过滤行或更改空值的显示方式。
select
EmpID,
EmpName,
[Type],
Units,
Account
from
(
select
EmpID,
EmpName,
[Type],
sum(Units) AS Units,
Account
from mytable
group by EmpID, EmpName, [Type], Account with CUBE
) s
where s.yourfilter
链接:https://technet.microsoft.com/en-us/library/ms175939(v=sql.90).aspx
答案 1 :(得分:0)
你对ROLLUP的期待太多了我觉得 - 这是我的建议样本,我无法完全摆脱CASE-s,但结果看起来像你的目标:
DECLARE @Data TABLE (
EmpID INT,
EmpName VARCHAR(100),
StartDate DATE,
[Type] VARCHAR(10),
Units DECIMAL(10, 3),
Account VARCHAR(100),
Dist INT
);
INSERT INTO
@Data
VALUES
(11111, 'Alice', '2015-09-04', 'SD20', 0.500, '560.2200', 100),
(11111, 'Alice', '2015-09-08', 'CCS', 1.330, '9P0.6010', 38),
(11111, 'Alice', '2015-09-08', 'CCS', 2.170, '010.9055', 62),
(11111, 'Alice', '2015-09-10', 'SD20', 0.500, 'LP0.3002', 100),
(11111, 'Alice', '2015-09-14', 'SD20', 0.500, 'LP0.3002', 100),
(11111, 'Alice', '2015-09-17', 'SD20', 1.000, 'LP0.P303', 100),
(11111, 'Alice', '2015-09-18', 'SD20', 1.000, '600.2200', 100),
(11111, 'Alice', '2015-09-24', 'SD20', 1.000, 'LP0.3002', 100),
(11111, 'Alice', '2015-09-25', 'SD20', 1.000, 'LP0.3002', 100),
(11111, 'Alice', '2015-09-29', 'SD20', 1.000, 'LP0.3002', 100),
(33333, 'Carol', '2015-09-03', 'SD20', 1.000, '9P0.PP10', 100),
(33333, 'Carol', '2015-09-04', 'SD20', 0.200, '600.6P62', 20),
(33333, 'Carol', '2015-09-04', 'SD20', 0.800, '600.6P62', 80),
(33333, 'Carol', '2015-09-25', 'SD20', 1.000, 'P50.2100', 100)
SELECT
CASE
WHEN RN = 0 THEN OrigEmpID
ELSE NULL
END AS EmpID,
CASE
WHEN RN = 0 THEN EmpName
ELSE NULL
END AS EmpName,
CASE
WHEN RN = 0 THEN NULL
WHEN RN = 3 THEN 'Subtotal'
ELSE [OrigType]
END AS [Type],
Units,
Account
FROM (
SELECT DISTINCT
0 AS RN,
EmpID AS OrigEmpID,
EmpName,
cast(NULL AS VARCHAR(10)) AS [OrigType],
cast(NULL AS DECIMAL(10,3)) AS Units,
cast(NULL AS VARCHAR(100)) AS Account
FROM
@Data
UNION ALL
SELECT
CASE WHEN Account IS NULL THEN 3 ELSE 2 END RN,
EmpID AS OrigEmpID,
EmpName,
[Type] AS [OrigType],
sum(Units) AS Units,
Account
FROM
@Data
GROUP BY
EmpID, EmpName, [Type], ROLLUP(Account)
) data
ORDER BY
OrigEmpID, [OrigType], RN, Account